blob: 11ae1ded584309a0497c2a0ead62426c44b36576 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03003# ABI Compliance Checker (ABICC) 1.99.13
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 Ponomarenko1fbbce62015-10-13 00:08:59 +030067my $TOOL_VERSION = "1.99.13";
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 Ponomarenko1fbbce62015-10-13 00:08:59 +030096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat,
97$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
98$TypesListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040099
100my $CmdName = get_filename($0);
101my %OS_LibExt = (
102 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400103 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400104 "macos"=>"dylib",
105 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400106 "symbian"=>"dso",
107 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400108 },
109 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400111 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400112 "symbian"=>"lib",
113 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400114 }
115);
116
117my %OS_Archive = (
118 "windows"=>"zip",
119 "default"=>"tar.gz"
120);
121
122my %ERROR_CODE = (
123 # Compatible verdict
124 "Compatible"=>0,
125 "Success"=>0,
126 # Incompatible verdict
127 "Incompatible"=>1,
128 # Undifferentiated error code
129 "Error"=>2,
130 # System command is not found
131 "Not_Found"=>3,
132 # Cannot access input files
133 "Access_Error"=>4,
134 # Cannot compile header files
135 "Cannot_Compile"=>5,
136 # Header compiled with errors
137 "Compile_Error"=>6,
138 # Invalid input ABI dump
139 "Invalid_Dump"=>7,
140 # Incompatible version of ABI dump
141 "Dump_Version"=>8,
142 # Cannot find a module
143 "Module_Error"=>9,
144 # Empty intersection between
145 # headers and shared objects
146 "Empty_Intersection"=>10,
147 # Empty set of symbols in headers
148 "Empty_Set"=>11
149);
150
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300151my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400152
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400153my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400154A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300155Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400156License: GNU LGPL or GNU GPL
157
158Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400159Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400160
161OLD.xml and NEW.xml are XML-descriptors:
162
163 <version>
164 1.0
165 </version>
166
167 <headers>
168 /path/to/headers/
169 </headers>
170
171 <libs>
172 /path/to/libraries/
173 </libs>
174
175More info: $CmdName --help\n";
176
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400177if($#ARGV==-1)
178{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400179 printMsg("INFO", $ShortUsage);
180 exit(0);
181}
182
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400183GetOptions("h|help!" => \$Help,
184 "i|info!" => \$InfoMsg,
185 "v|version!" => \$ShowVersion,
186 "dumpversion!" => \$DumpVersion,
187# general options
188 "l|lib|library=s" => \$TargetLibraryName,
189 "d1|old|o=s" => \$Descriptor{1}{"Path"},
190 "d2|new|n=s" => \$Descriptor{2}{"Path"},
191 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400192# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193 "app|application=s" => \$AppPath,
194 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400195 "gcc-path|cross-gcc=s" => \$CrossGcc,
196 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
197 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400198 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300199 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
200 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400201 "s|strict!" => \$StrictCompat,
202 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300203 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400204 "skip-symbols=s" => \$SkipSymbolsListPath,
205 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400206 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400207 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400208 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400209 "show-retval!" => \$ShowRetVal,
210 "use-dumps!" => \$UseDumps,
211 "nostdinc!" => \$NoStdInc,
212 "dump-system=s" => \$DumpSystem,
213 "sysinfo=s" => \$TargetSysInfo,
214 "cmp-systems!" => \$CmpSystems,
215 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400216 "ext|extended!" => \$ExtendedCheck,
217 "q|quiet!" => \$Quiet,
218 "stdout!" => \$StdOut,
219 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400220 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400221 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400222 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400223 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400224 "binary|bin|abi!" => \$BinaryOnly,
225 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400226 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400227# other options
228 "test!" => \$TestTool,
229 "test-dump!" => \$TestDump,
230 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400231 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400232 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400233 "p|params=s" => \$ParamNamesPath,
234 "relpath1|relpath=s" => \$RelativeDirectory{1},
235 "relpath2=s" => \$RelativeDirectory{2},
236 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400237 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400239 "bin-report-path=s" => \$BinaryReportPath,
240 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400241 "log-path=s" => \$LoggingPath,
242 "log1-path=s" => \$OutputLogPath{1},
243 "log2-path=s" => \$OutputLogPath{2},
244 "logging-mode=s" => \$LogMode,
245 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300246 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400248 "extra-info=s" => \$ExtraInfo,
249 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400250 "force!" => \$Force,
251 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400252 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400253 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400254 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400255 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300256 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
257 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400258) or ERR_MESSAGE();
259
260sub ERR_MESSAGE()
261{
262 printMsg("INFO", "\n".$ShortUsage);
263 exit($ERROR_CODE{"Error"});
264}
265
266my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
267my $SLIB_TYPE = $LIB_TYPE;
268if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
269{ # show as "shared" library
270 $SLIB_TYPE = "shared";
271}
272my $LIB_EXT = getLIB_EXT($OSgroup);
273my $AR_EXT = getAR_EXT($OSgroup);
274my $BYTE_SIZE = 8;
275my $COMMON_LOG_PATH = "logs/run.log";
276
277my $HelpMessage="
278NAME:
279 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400280 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400281
282DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400283 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400284 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
285 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
286 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
287 and/or source-level compatibility: changes in calling stack, v-table changes,
288 removed symbols, renamed fields, etc. Binary incompatibility may result in
289 crashing or incorrect behavior of applications built with an old version of
290 a library if they run on a new one. Source incompatibility may result in
291 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400292
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400293 The tool is intended for developers of software libraries and maintainers
294 of operating systems who are interested in ensuring backward compatibility,
295 i.e. allow old applications to run or to be recompiled with newer library
296 versions.
297
298 Also the tool can be used by ISVs for checking applications portability to
299 new library versions. Found issues can be taken into account when adapting
300 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400301
302 This tool is free software: you can redistribute it and/or modify it
303 under the terms of the GNU LGPL or GNU GPL.
304
305USAGE:
306 $CmdName [options]
307
308EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400309 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400310
311 OLD.xml and NEW.xml are XML-descriptors:
312
313 <version>
314 1.0
315 </version>
316
317 <headers>
318 /path1/to/header(s)/
319 /path2/to/header(s)/
320 ...
321 </headers>
322
323 <libs>
324 /path1/to/library(ies)/
325 /path2/to/library(ies)/
326 ...
327 </libs>
328
329INFORMATION OPTIONS:
330 -h|-help
331 Print this help.
332
333 -i|-info
334 Print complete info.
335
336 -v|-version
337 Print version information.
338
339 -dumpversion
340 Print the tool version ($TOOL_VERSION) and don't do anything else.
341
342GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400343 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400344 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400346 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400347 Descriptor of 1st (old) library version.
348 It may be one of the following:
349
350 1. XML-descriptor (VERSION.xml file):
351
352 <version>
353 1.0
354 </version>
355
356 <headers>
357 /path1/to/header(s)/
358 /path2/to/header(s)/
359 ...
360 </headers>
361
362 <libs>
363 /path1/to/library(ies)/
364 /path2/to/library(ies)/
365 ...
366 </libs>
367
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300368 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400369
370 2. ABI dump generated by -dump option
371 3. Directory with headers and/or $SLIB_TYPE libraries
372 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400373
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300374 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400375 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400376
377 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400378 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400380 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400381 Descriptor of 2nd (new) library version.
382
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400383 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400384 Create library ABI dump for the input XML descriptor. You can
385 transfer it anywhere and pass instead of the descriptor. Also
386 it can be used for debugging the tool.
387
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300388 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400389
390sub HELP_MESSAGE() {
391 printMsg("INFO", $HelpMessage."
392MORE INFO:
393 $CmdName --info\n");
394}
395
396sub INFO_MESSAGE()
397{
398 printMsg("INFO", "$HelpMessage
399EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400400 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300401 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402 for portability to the new library version.
403
404 -static-libs
405 Check static libraries instead of the shared ones. The <libs> section
406 of the XML-descriptor should point to static libraries location.
407
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300408 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400409 Path to the cross GCC compiler to use instead of the usual (host) GCC.
410
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300411 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400412 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300413
414 -gcc-options OPTS
415 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400417 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400420
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400421 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200423 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400424
425 In general case you should specify it in the XML-descriptor:
426 <version>
427 VERSION
428 </version>
429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400430 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400431 Specify 2nd library version outside the descriptor.
432
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400433 -vnum NUM
434 Specify the library version in the generated ABI dump. The <version> section
435 of the input XML descriptor will be overwritten in this case.
436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437 -s|-strict
438 Treat all compatibility warnings as problems. Add a number of \"Low\"
439 severity problems to the return value of the tool.
440
441 -headers-only
442 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
443 provide a low quality compatibility report with false positives and
444 without detecting of added/removed symbols.
445
446 Alternatively you can write \"none\" word to the <libs> section
447 in the XML-descriptor:
448 <libs>
449 none
450 </libs>
451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400452 -show-retval
453 Show the symbol's return type in the report.
454
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400455 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300456 This option allows to specify a file with a list of symbols (mangled
457 names in C++) that should be checked. Other symbols will not be checked.
458
459 -types-list PATH
460 This option allows to specify a file with a list of types that should
461 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400462
463 -skip-symbols PATH
464 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400465
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400466 -headers-list PATH
467 The file with a list of headers, that should be checked/dumped.
468
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400469 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400470 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400471
472 -header NAME
473 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400474
475 -use-dumps
476 Make dumps for two versions of a library and compare dumps. This should
477 increase the performance of the tool and decrease the system memory usage.
478
479 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400480 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400481
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400482 -dump-system NAME -sysroot DIR
483 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400484 create XML descriptors and make ABI dumps for each library. The result
485 set of ABI dumps can be compared (--cmp-systems) with the other one
486 created for other version of operating system in order to check them for
487 compatibility. Do not forget to specify -cross-gcc option if your target
488 system requires some specific version of GCC compiler (different from
489 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400490 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400491
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400492 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400493 The same as the previous option but takes an XML descriptor of the target
494 system as input, where you should describe it:
495
496 /* Primary sections */
497
498 <name>
499 /* Name of the system */
500 </name>
501
502 <headers>
503 /* The list of paths to header files and/or
504 directories with header files, one per line */
505 </headers>
506
507 <libs>
508 /* The list of paths to shared libraries and/or
509 directories with shared libraries, one per line */
510 </libs>
511
512 /* Optional sections */
513
514 <search_headers>
515 /* List of directories to be searched
516 for header files to automatically
517 generate include paths, one per line */
518 </search_headers>
519
520 <search_libs>
521 /* List of directories to be searched
522 for shared libraries to resolve
523 dependencies, one per line */
524 </search_libs>
525
526 <tools>
527 /* List of directories with tools used
528 for analysis (GCC toolchain), one per line */
529 </tools>
530
531 <cross_prefix>
532 /* GCC toolchain prefix.
533 Examples:
534 arm-linux-gnueabi
535 arm-none-symbianelf */
536 </cross_prefix>
537
538 <gcc_options>
539 /* Additional GCC options, one per line */
540 </gcc_options>
541
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400542 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300543 This option should be used with -dump-system option to dump
544 ABI of operating systems and configure the dumping process.
545 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400546 modules/Targets/{unix, symbian, windows}
547
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400548 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400549 Compare two system ABI dumps. Create compatibility reports for each
550 library and the common HTML report including the summary of test
551 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400552 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400554 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400555 The file with a list of libraries, that should be dumped by
556 the -dump-system option or should be checked by the -cmp-systems option.
557
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400558 -ext|-extended
559 If your library A is supposed to be used by other library B and you
560 want to control the ABI of B, then you should enable this option. The
561 tool will check for changes in all data types, even if they are not
562 used by any function in the library A. Such data types are not part
563 of the A library ABI, but may be a part of the ABI of the B library.
564
565 The short scheme is:
566 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
567
568 -q|-quiet
569 Print all messages to the file instead of stdout and stderr.
570 Default path (can be changed by -log-path option):
571 $COMMON_LOG_PATH
572
573 -stdout
574 Print analysis results (compatibility reports and ABI dumps) to stdout
575 instead of creating a file. This would allow piping data to other programs.
576
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400577 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400578 Change format of compatibility report.
579 Formats:
580 htm - HTML format (default)
581 xml - XML format
582
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400583 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400584 Change format of ABI dump.
585 Formats:
586 perl - Data::Dumper format (default)
587 xml - XML format
588
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400589 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400590 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400591
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400592 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400593 Set library language (C or C++). You can use this option if the tool
594 cannot auto-detect a language. This option may be useful for checking
595 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400596
597 -arch ARCH
598 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
599 ect.). The option is useful if the tool cannot detect correct architecture
600 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400601
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400602 -binary|-bin|-abi
603 Show \"Binary\" compatibility problems only.
604 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400605 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400606
607 -source|-src|-api
608 Show \"Source\" compatibility problems only.
609 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400610 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400611
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400612 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400613 The maximum number of affected symbols listed under the description
614 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400615
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400616OTHER OPTIONS:
617 -test
618 Run internal tests. Create two binary incompatible versions of a sample
619 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300620 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400621
622 -test-dump
623 Test ability to create, read and compare ABI dumps.
624
625 -debug
626 Debugging mode. Print debug info on the screen. Save intermediate
627 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400628 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400629
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400630 Also consider using --dump option for debugging the tool.
631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400632 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400633 If your header files are written in C language and can be compiled
634 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
635 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400636
637 -cpp-incompatible
638 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400639
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400640 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400641 Path to file with the function parameter names. It can be used
642 for improving report view if the library header files have no
643 parameter names. File format:
644
645 func1;param1;param2;param3 ...
646 func2;param1;param2;param3 ...
647 ...
648
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400649 -relpath PATH
650 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400651 for dumping the library ABI (see -dump option).
652
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400653 -relpath1 PATH
654 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400655
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400656 -relpath2 PATH
657 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400658
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400659 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400660 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400664 -sort
665 Enable sorting of data in ABI dumps.
666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400668 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400669 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400671
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400672 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400673 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400674 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400678 Path to \"Source\" compatibility report.
679 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400681
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400682 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683 Log path for all messages.
684 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400688 Log path for 1st version of a library.
689 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693 Log path for 2nd version of a library.
694 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400698 Change logging mode.
699 Modes:
700 w - overwrite old logs (default)
701 a - append old logs
702 n - do not write any logs
703
704 -list-affected
705 Generate file with the list of incompatible
706 symbols beside the HTML compatibility report.
707 Use 'c++filt \@file' command from GNU binutils
708 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400709 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400710 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400711 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400712
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714 The component name in the title and summary of the HTML report.
715 Default:
716 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300717
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300718 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400721
722 -extra-info DIR
723 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400724
725 -extra-dump
726 Create extended ABI dump containing all symbols
727 from the translation unit.
728
729 -force
730 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400731
732 -tolerance LEVEL
733 Apply a set of heuristics to successfully compile input
734 header files. You can enable several tolerance levels by
735 joining them into one string (e.g. 13, 124, etc.).
736 Levels:
737 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
738 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
739 3 - skip headers that iclude non-Linux headers
740 4 - skip headers included by others
741
742 -tolerant
743 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400744
745 -check
746 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400747
748 -quick
749 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400750
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300751 -skip-internal-symbols PATTERN
752 Do not check symbols matched by the pattern.
753
754 -skip-internal-types PATTERN
755 Do not check types matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400756
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400757REPORT:
758 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400759 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400760
761 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400762 logs/LIB_NAME/V1/log.txt
763 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400764
765EXIT CODES:
766 0 - Compatible. The tool has run without any errors.
767 non-zero - Incompatible or the tool has run with errors.
768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400769MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300770 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400771}
772
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400773my %Operator_Indication = (
774 "not" => "~",
775 "assign" => "=",
776 "andassign" => "&=",
777 "orassign" => "|=",
778 "xorassign" => "^=",
779 "or" => "|",
780 "xor" => "^",
781 "addr" => "&",
782 "and" => "&",
783 "lnot" => "!",
784 "eq" => "==",
785 "ne" => "!=",
786 "lt" => "<",
787 "lshift" => "<<",
788 "lshiftassign" => "<<=",
789 "rshiftassign" => ">>=",
790 "call" => "()",
791 "mod" => "%",
792 "modassign" => "%=",
793 "subs" => "[]",
794 "land" => "&&",
795 "lor" => "||",
796 "rshift" => ">>",
797 "ref" => "->",
798 "le" => "<=",
799 "deref" => "*",
800 "mult" => "*",
801 "preinc" => "++",
802 "delete" => " delete",
803 "vecnew" => " new[]",
804 "vecdelete" => " delete[]",
805 "predec" => "--",
806 "postinc" => "++",
807 "postdec" => "--",
808 "plusassign" => "+=",
809 "plus" => "+",
810 "minus" => "-",
811 "minusassign" => "-=",
812 "gt" => ">",
813 "ge" => ">=",
814 "new" => " new",
815 "multassign" => "*=",
816 "divassign" => "/=",
817 "div" => "/",
818 "neg" => "-",
819 "pos" => "+",
820 "memref" => "->*",
821 "compound" => "," );
822
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400823my %UnknownOperator;
824
825my %NodeType= (
826 "array_type" => "Array",
827 "binfo" => "Other",
828 "boolean_type" => "Intrinsic",
829 "complex_type" => "Intrinsic",
830 "const_decl" => "Other",
831 "enumeral_type" => "Enum",
832 "field_decl" => "Other",
833 "function_decl" => "Other",
834 "function_type" => "FunctionType",
835 "identifier_node" => "Other",
836 "integer_cst" => "Other",
837 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400838 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400839 "method_type" => "MethodType",
840 "namespace_decl" => "Other",
841 "parm_decl" => "Other",
842 "pointer_type" => "Pointer",
843 "real_cst" => "Other",
844 "real_type" => "Intrinsic",
845 "record_type" => "Struct",
846 "reference_type" => "Ref",
847 "string_cst" => "Other",
848 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400849 "template_type_parm" => "TemplateParam",
850 "typename_type" => "TypeName",
851 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400852 "tree_list" => "Other",
853 "tree_vec" => "Other",
854 "type_decl" => "Other",
855 "union_type" => "Union",
856 "var_decl" => "Other",
857 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400858 "nop_expr" => "Other", #
859 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400860 "offset_type" => "Other" );
861
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400862my %CppKeywords_C = map {$_=>1} (
863 # C++ 2003 keywords
864 "public",
865 "protected",
866 "private",
867 "default",
868 "template",
869 "new",
870 #"asm",
871 "dynamic_cast",
872 "auto",
873 "try",
874 "namespace",
875 "typename",
876 "using",
877 "reinterpret_cast",
878 "friend",
879 "class",
880 "virtual",
881 "const_cast",
882 "mutable",
883 "static_cast",
884 "export",
885 # C++0x keywords
886 "noexcept",
887 "nullptr",
888 "constexpr",
889 "static_assert",
890 "explicit",
891 # cannot be used as a macro name
892 # as it is an operator in C++
893 "and",
894 #"and_eq",
895 "not",
896 #"not_eq",
897 "or"
898 #"or_eq",
899 #"bitand",
900 #"bitor",
901 #"xor",
902 #"xor_eq",
903 #"compl"
904);
905
906my %CppKeywords_F = map {$_=>1} (
907 "delete",
908 "catch",
909 "alignof",
910 "thread_local",
911 "decltype",
912 "typeid"
913);
914
915my %CppKeywords_O = map {$_=>1} (
916 "bool",
917 "register",
918 "inline",
919 "operator"
920);
921
922my %CppKeywords_A = map {$_=>1} (
923 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400924 "throw",
925 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400926);
927
928foreach (keys(%CppKeywords_C),
929keys(%CppKeywords_F),
930keys(%CppKeywords_O)) {
931 $CppKeywords_A{$_}=1;
932}
933
934# Header file extensions as described by gcc
935my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
936
937my %IntrinsicMangling = (
938 "void" => "v",
939 "bool" => "b",
940 "wchar_t" => "w",
941 "char" => "c",
942 "signed char" => "a",
943 "unsigned char" => "h",
944 "short" => "s",
945 "unsigned short" => "t",
946 "int" => "i",
947 "unsigned int" => "j",
948 "long" => "l",
949 "unsigned long" => "m",
950 "long long" => "x",
951 "__int64" => "x",
952 "unsigned long long" => "y",
953 "__int128" => "n",
954 "unsigned __int128" => "o",
955 "float" => "f",
956 "double" => "d",
957 "long double" => "e",
958 "__float80" => "e",
959 "__float128" => "g",
960 "..." => "z"
961);
962
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400963my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
964
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400965my %StdcxxMangling = (
966 "3std"=>"St",
967 "3std9allocator"=>"Sa",
968 "3std12basic_string"=>"Sb",
969 "3std12basic_stringIcE"=>"Ss",
970 "3std13basic_istreamIcE"=>"Si",
971 "3std13basic_ostreamIcE"=>"So",
972 "3std14basic_iostreamIcE"=>"Sd"
973);
974
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400975my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400976my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
977
978my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400979my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400981my %ConstantSuffix = (
982 "unsigned int"=>"u",
983 "long"=>"l",
984 "unsigned long"=>"ul",
985 "long long"=>"ll",
986 "unsigned long long"=>"ull"
987);
988
989my %ConstantSuffixR =
990reverse(%ConstantSuffix);
991
992my %OperatorMangling = (
993 "~" => "co",
994 "=" => "aS",
995 "|" => "or",
996 "^" => "eo",
997 "&" => "an",#ad (addr)
998 "==" => "eq",
999 "!" => "nt",
1000 "!=" => "ne",
1001 "<" => "lt",
1002 "<=" => "le",
1003 "<<" => "ls",
1004 "<<=" => "lS",
1005 ">" => "gt",
1006 ">=" => "ge",
1007 ">>" => "rs",
1008 ">>=" => "rS",
1009 "()" => "cl",
1010 "%" => "rm",
1011 "[]" => "ix",
1012 "&&" => "aa",
1013 "||" => "oo",
1014 "*" => "ml",#de (deref)
1015 "++" => "pp",#
1016 "--" => "mm",#
1017 "new" => "nw",
1018 "delete" => "dl",
1019 "new[]" => "na",
1020 "delete[]" => "da",
1021 "+=" => "pL",
1022 "+" => "pl",#ps (pos)
1023 "-" => "mi",#ng (neg)
1024 "-=" => "mI",
1025 "*=" => "mL",
1026 "/=" => "dV",
1027 "&=" => "aN",
1028 "|=" => "oR",
1029 "%=" => "rM",
1030 "^=" => "eO",
1031 "/" => "dv",
1032 "->*" => "pm",
1033 "->" => "pt",#rf (ref)
1034 "," => "cm",
1035 "?" => "qu",
1036 "." => "dt",
1037 "sizeof"=> "sz"#st
1038);
1039
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001040my %Intrinsic_Keywords = map {$_=>1} (
1041 "true",
1042 "false",
1043 "_Bool",
1044 "_Complex",
1045 "const",
1046 "int",
1047 "long",
1048 "void",
1049 "short",
1050 "float",
1051 "volatile",
1052 "restrict",
1053 "unsigned",
1054 "signed",
1055 "char",
1056 "double",
1057 "class",
1058 "struct",
1059 "union",
1060 "enum"
1061);
1062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001063my %GlibcHeader = map {$_=>1} (
1064 "aliases.h",
1065 "argp.h",
1066 "argz.h",
1067 "assert.h",
1068 "cpio.h",
1069 "ctype.h",
1070 "dirent.h",
1071 "envz.h",
1072 "errno.h",
1073 "error.h",
1074 "execinfo.h",
1075 "fcntl.h",
1076 "fstab.h",
1077 "ftw.h",
1078 "glob.h",
1079 "grp.h",
1080 "iconv.h",
1081 "ifaddrs.h",
1082 "inttypes.h",
1083 "langinfo.h",
1084 "limits.h",
1085 "link.h",
1086 "locale.h",
1087 "malloc.h",
1088 "math.h",
1089 "mntent.h",
1090 "monetary.h",
1091 "nl_types.h",
1092 "obstack.h",
1093 "printf.h",
1094 "pwd.h",
1095 "regex.h",
1096 "sched.h",
1097 "search.h",
1098 "setjmp.h",
1099 "shadow.h",
1100 "signal.h",
1101 "spawn.h",
1102 "stdarg.h",
1103 "stdint.h",
1104 "stdio.h",
1105 "stdlib.h",
1106 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001107 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001108 "tar.h",
1109 "termios.h",
1110 "time.h",
1111 "ulimit.h",
1112 "unistd.h",
1113 "utime.h",
1114 "wchar.h",
1115 "wctype.h",
1116 "wordexp.h" );
1117
1118my %GlibcDir = map {$_=>1} (
1119 "arpa",
1120 "bits",
1121 "gnu",
1122 "netinet",
1123 "net",
1124 "nfs",
1125 "rpc",
1126 "sys",
1127 "linux" );
1128
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001129my %WinHeaders = map {$_=>1} (
1130 "dos.h",
1131 "process.h",
1132 "winsock.h",
1133 "config-win.h",
1134 "mem.h",
1135 "windows.h",
1136 "winsock2.h",
1137 "crtdbg.h",
1138 "ws2tcpip.h"
1139);
1140
1141my %ObsoleteHeaders = map {$_=>1} (
1142 "iostream.h",
1143 "fstream.h"
1144);
1145
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001146my %AlienHeaders = map {$_=>1} (
1147 # Solaris
1148 "thread.h",
1149 "sys/atomic.h",
1150 # HPUX
1151 "sys/stream.h",
1152 # Symbian
1153 "AknDoc.h",
1154 # Atari ST
1155 "ext.h",
1156 "tos.h",
1157 # MS-DOS
1158 "alloc.h",
1159 # Sparc
1160 "sys/atomic.h"
1161);
1162
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001163my %ConfHeaders = map {$_=>1} (
1164 "atomic",
1165 "conf.h",
1166 "config.h",
1167 "configure.h",
1168 "build.h",
1169 "setup.h"
1170);
1171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001172my %LocalIncludes = map {$_=>1} (
1173 "/usr/local/include",
1174 "/usr/local" );
1175
1176my %OS_AddPath=(
1177# These paths are needed if the tool cannot detect them automatically
1178 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001179 "include"=>[
1180 "/Library",
1181 "/Developer/usr/include"
1182 ],
1183 "lib"=>[
1184 "/Library",
1185 "/Developer/usr/lib"
1186 ],
1187 "bin"=>[
1188 "/Developer/usr/bin"
1189 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001190 },
1191 "beos"=>{
1192 # Haiku has GCC 2.95.3 by default
1193 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001194 "include"=>[
1195 "/boot/common",
1196 "/boot/develop"
1197 ],
1198 "lib"=>[
1199 "/boot/common/lib",
1200 "/boot/system/lib",
1201 "/boot/apps"
1202 ],
1203 "bin"=>[
1204 "/boot/common/bin",
1205 "/boot/system/bin",
1206 "/boot/develop/abi"
1207 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001209);
1210
1211my %Slash_Type=(
1212 "default"=>"/",
1213 "windows"=>"\\"
1214);
1215
1216my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1217
1218# Global Variables
1219my %COMMON_LANGUAGE=(
1220 1 => "C",
1221 2 => "C" );
1222
1223my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001224my $MAX_CPPFILT_FILE_SIZE = 50000;
1225my $CPPFILT_SUPPORT_FILE;
1226
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001227my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001229my $STDCXX_TESTING = 0;
1230my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001231my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001232
1233my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001234my $CheckUndefined = 0;
1235
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001236my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001237if($TargetComponent_Opt) {
1238 $TargetComponent = lc($TargetComponent_Opt);
1239}
1240else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001241{ # default: library
1242 # other components: header, system, ...
1243 $TargetComponent = "library";
1244}
1245
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001246my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001247
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001248my $SystemRoot;
1249
1250my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001251my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001252my %LOG_PATH;
1253my %DEBUG_PATH;
1254my %Cache;
1255my %LibInfo;
1256my $COMPILE_ERRORS = 0;
1257my %CompilerOptions;
1258my %CheckedDyLib;
1259my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1260
1261# Constants (#defines)
1262my %Constants;
1263my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001264my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001265
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001266# Extra Info
1267my %SymbolHeader;
1268my %KnownLibs;
1269
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001270# Templates
1271my %TemplateInstance;
1272my %BasicTemplate;
1273my %TemplateArg;
1274my %TemplateDecl;
1275my %TemplateMap;
1276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001277# Types
1278my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001279my %SkipTypes = (
1280 "1"=>{},
1281 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001282my %CheckedTypes;
1283my %TName_Tid;
1284my %EnumMembName_Id;
1285my %NestedNameSpaces = (
1286 "1"=>{},
1287 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001288my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001289my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001290my %ClassVTable;
1291my %ClassVTable_Content;
1292my %VTableClass;
1293my %AllocableClass;
1294my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001295my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296my %Class_SubClasses;
1297my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001298my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001299my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001301my %CheckedTypeInfo;
1302
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001303# Typedefs
1304my %Typedef_BaseName;
1305my %Typedef_Tr;
1306my %Typedef_Eq;
1307my %StdCxxTypedef;
1308my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001309my %MissedBase;
1310my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001311my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001312
1313# Symbols
1314my %SymbolInfo;
1315my %tr_name;
1316my %mangled_name_gcc;
1317my %mangled_name;
1318my %SkipSymbols = (
1319 "1"=>{},
1320 "2"=>{} );
1321my %SkipNameSpaces = (
1322 "1"=>{},
1323 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001324my %AddNameSpaces = (
1325 "1"=>{},
1326 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001327my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001328my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001329my %SymbolsList_App;
1330my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001331my %Symbol_Library = (
1332 "1"=>{},
1333 "2"=>{} );
1334my %Library_Symbol = (
1335 "1"=>{},
1336 "2"=>{} );
1337my %DepSymbol_Library = (
1338 "1"=>{},
1339 "2"=>{} );
1340my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341 "1"=>{},
1342 "2"=>{} );
1343my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001344my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001345my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001346my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001347my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001348my %Library_Needed= (
1349 "1"=>{},
1350 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001352# Extra Info
1353my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001354my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001355
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001356# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001357my %Include_Preamble = (
1358 "1"=>[],
1359 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001360my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001361my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001362my %HeaderName_Paths;
1363my %Header_Dependency;
1364my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001365my %Include_Paths = (
1366 "1"=>[],
1367 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001368my %INC_PATH_AUTODETECT = (
1369 "1"=>1,
1370 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001371my %Add_Include_Paths = (
1372 "1"=>[],
1373 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374my %Skip_Include_Paths;
1375my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376my %Header_ErrorRedirect;
1377my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001378my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001379my %Header_ShouldNotBeUsed;
1380my %RecursiveIncludes;
1381my %Header_Include_Prefix;
1382my %SkipHeaders;
1383my %SkipHeadersList=(
1384 "1"=>{},
1385 "2"=>{} );
1386my %SkipLibs;
1387my %Include_Order;
1388my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001389my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001390my %TUnit_Funcs;
1391my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001392
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001393my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001394 "1"=>0,
1395 "2"=>0 );
1396my %AutoPreambleMode = (
1397 "1"=>0,
1398 "2"=>0 );
1399my %MinGWMode = (
1400 "1"=>0,
1401 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001402my %Cpp0xMode = (
1403 "1"=>0,
1404 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001405
1406# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001407my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001408my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001409my %RegisteredSONAMEs;
1410my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001412my %CheckedArch;
1413
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001414# System Objects
1415my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001416my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001417my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418
1419# System Headers
1420my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001421my @DefaultCppPaths;
1422my @DefaultGccPaths;
1423my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424my %DefaultCppHeader;
1425my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001426my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001427
1428# Merging
1429my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001430my $Version;
1431my %AddedInt;
1432my %RemovedInt;
1433my %AddedInt_Virt;
1434my %RemovedInt_Virt;
1435my %VirtualReplacement;
1436my %ChangedTypedef;
1437my %CompatRules;
1438my %IncompleteRules;
1439my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001440my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001441my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001442my %ReturnedClass;
1443my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001444my %SourceAlternative;
1445my %SourceAlternative_B;
1446my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001447my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001448
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001449# Calling Conventions
1450my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001451 1=>{ "R"=>0, "P"=>0 },
1452 2=>{ "R"=>0, "P"=>0 }
1453);
1454
1455# ABI Dump
1456my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001457
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001458# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001459my %TargetLibs;
1460my %TargetHeaders;
1461
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001462# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001463my $OStarget = $OSgroup;
1464my %TargetTools;
1465
1466# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001467my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001468
1469# Recursion locks
1470my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001472my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001473my @RecurInclude;
1474my @RecurConstant;
1475
1476# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001477my %SystemPaths = (
1478 "include"=>[],
1479 "lib"=>[],
1480 "bin"=>[]
1481);
1482my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001483my $GCC_PATH;
1484
1485# Symbols versioning
1486my %SymVer = (
1487 "1"=>{},
1488 "2"=>{} );
1489
1490# Problem descriptions
1491my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001492my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001493my %TotalAffected;
1494
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001495# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001496my $ContentID = 1;
1497my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1498my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1499my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1500my $ContentSpanEnd = "</span>\n";
1501my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1502my $ContentDivEnd = "</div>\n";
1503my $Content_Counter = 0;
1504
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001505# Modes
1506my $JoinReport = 1;
1507my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001508
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001509my %Severity_Val=(
1510 "High"=>3,
1511 "Medium"=>2,
1512 "Low"=>1,
1513 "Safe"=>-1
1514);
1515
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001516sub get_Modules()
1517{
1518 my $TOOL_DIR = get_dirname($0);
1519 if(not $TOOL_DIR)
1520 { # patch for MS Windows
1521 $TOOL_DIR = ".";
1522 }
1523 my @SEARCH_DIRS = (
1524 # tool's directory
1525 abs_path($TOOL_DIR),
1526 # relative path to modules
1527 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001528 # install path
1529 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001530 );
1531 foreach my $DIR (@SEARCH_DIRS)
1532 {
1533 if(not is_abs($DIR))
1534 { # relative path
1535 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1536 }
1537 if(-d $DIR."/modules") {
1538 return $DIR."/modules";
1539 }
1540 }
1541 exitStatus("Module_Error", "can't find modules");
1542}
1543
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001544my %LoadedModules = ();
1545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001546sub loadModule($)
1547{
1548 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001549 if(defined $LoadedModules{$Name}) {
1550 return;
1551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1553 if(not -f $Path) {
1554 exitStatus("Module_Error", "can't access \'$Path\'");
1555 }
1556 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001557 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001558}
1559
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001560sub readModule($$)
1561{
1562 my ($Module, $Name) = @_;
1563 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1564 if(not -f $Path) {
1565 exitStatus("Module_Error", "can't access \'$Path\'");
1566 }
1567 return readFile($Path);
1568}
1569
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001570sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001571{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001572 my $Number = $_[0];
1573 if(not $Number) {
1574 $Number = 1;
1575 }
1576 else {
1577 $Number = int($Number)+1;
1578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579 if($Number>3) {
1580 return $Number."th";
1581 }
1582 elsif($Number==1) {
1583 return "1st";
1584 }
1585 elsif($Number==2) {
1586 return "2nd";
1587 }
1588 elsif($Number==3) {
1589 return "3rd";
1590 }
1591 else {
1592 return $Number;
1593 }
1594}
1595
1596sub search_Tools($)
1597{
1598 my $Name = $_[0];
1599 return "" if(not $Name);
1600 if(my @Paths = keys(%TargetTools))
1601 {
1602 foreach my $Path (@Paths)
1603 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001604 if(-f join_P($Path, $Name)) {
1605 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001606 }
1607 if($CrossPrefix)
1608 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001609 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001610 if(-f $Candidate) {
1611 return $Candidate;
1612 }
1613 }
1614 }
1615 }
1616 else {
1617 return "";
1618 }
1619}
1620
1621sub synch_Cmd($)
1622{
1623 my $Name = $_[0];
1624 if(not $GCC_PATH)
1625 { # GCC was not found yet
1626 return "";
1627 }
1628 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001629 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001630 return $Candidate;
1631 }
1632 return "";
1633}
1634
1635sub get_CmdPath($)
1636{
1637 my $Name = $_[0];
1638 return "" if(not $Name);
1639 if(defined $Cache{"get_CmdPath"}{$Name}) {
1640 return $Cache{"get_CmdPath"}{$Name};
1641 }
1642 my %BinUtils = map {$_=>1} (
1643 "c++filt",
1644 "objdump",
1645 "readelf"
1646 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001647 if($BinUtils{$Name} and $GCC_PATH)
1648 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001649 if(my $Dir = get_dirname($GCC_PATH)) {
1650 $TargetTools{$Dir}=1;
1651 }
1652 }
1653 my $Path = search_Tools($Name);
1654 if(not $Path and $OSgroup eq "windows") {
1655 $Path = search_Tools($Name.".exe");
1656 }
1657 if(not $Path and $BinUtils{$Name})
1658 {
1659 if($CrossPrefix)
1660 { # user-defined prefix
1661 $Path = search_Cmd($CrossPrefix."-".$Name);
1662 }
1663 }
1664 if(not $Path and $BinUtils{$Name})
1665 {
1666 if(my $Candidate = synch_Cmd($Name))
1667 { # synch with GCC
1668 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001669 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001670 if(-f $Candidate) {
1671 $Path = $Candidate;
1672 }
1673 }
1674 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001675 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001676 $Path = $Candidate;
1677 }
1678 }
1679 }
1680 if(not $Path) {
1681 $Path = search_Cmd($Name);
1682 }
1683 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001684 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001685 $Path=search_Cmd($Name.".exe");
1686 }
1687 if($Path=~/\s/) {
1688 $Path = "\"".$Path."\"";
1689 }
1690 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1691}
1692
1693sub search_Cmd($)
1694{
1695 my $Name = $_[0];
1696 return "" if(not $Name);
1697 if(defined $Cache{"search_Cmd"}{$Name}) {
1698 return $Cache{"search_Cmd"}{$Name};
1699 }
1700 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1701 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1702 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001703 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001704 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001705 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001706 if(-f $CmdPath)
1707 {
1708 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001709 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001710 }
1711 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1712 }
1713 }
1714 return ($Cache{"search_Cmd"}{$Name} = "");
1715}
1716
1717sub get_CmdPath_Default($)
1718{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001719 return "" if(not $_[0]);
1720 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1721 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001722 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001723 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1724}
1725
1726sub get_CmdPath_Default_I($)
1727{ # search in PATH
1728 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001729 if($Name=~/find/)
1730 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001731 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001732 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733 }
1734 }
1735 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001737 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001738 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001739 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001740 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001741 if($OSgroup eq "windows")
1742 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001743 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001744 return $Name;
1745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001747 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 {
1749 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001750 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001751 }
1752 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001753 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754}
1755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001756sub classifyPath($)
1757{
1758 my $Path = $_[0];
1759 if($Path=~/[\*\[]/)
1760 { # wildcard
1761 $Path=~s/\*/.*/g;
1762 $Path=~s/\\/\\\\/g;
1763 return ($Path, "Pattern");
1764 }
1765 elsif($Path=~/[\/\\]/)
1766 { # directory or relative path
1767 return (path_format($Path, $OSgroup), "Path");
1768 }
1769 else {
1770 return ($Path, "Name");
1771 }
1772}
1773
1774sub readDescriptor($$)
1775{
1776 my ($LibVersion, $Content) = @_;
1777 return if(not $LibVersion);
1778 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1779 if(not $Content) {
1780 exitStatus("Error", "$DName is empty");
1781 }
1782 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001783 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001784 }
1785 $Content=~s/\/\*(.|\n)+?\*\///g;
1786 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001788 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1789 if($TargetVersion{$LibVersion}) {
1790 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1791 }
1792 if(not $Descriptor{$LibVersion}{"Version"}) {
1793 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1794 }
1795 if($Content=~/{RELPATH}/)
1796 {
1797 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1798 $Content =~ s/{RELPATH}/$RelDir/g;
1799 }
1800 else
1801 {
1802 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1803 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1804 }
1805 }
1806
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001807 my $DHeaders = parseTag(\$Content, "headers");
1808 if(not $DHeaders) {
1809 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1810 }
1811 elsif(lc($DHeaders) ne "none")
1812 { # append the descriptor headers list
1813 if($Descriptor{$LibVersion}{"Headers"})
1814 { # multiple descriptors
1815 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001816 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001817 else {
1818 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1819 }
1820 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1821 {
1822 if(not -e $Path) {
1823 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 }
1825 }
1826 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001828 if(not $CheckHeadersOnly_Opt)
1829 {
1830 my $DObjects = parseTag(\$Content, "libs");
1831 if(not $DObjects) {
1832 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1833 }
1834 elsif(lc($DObjects) ne "none")
1835 { # append the descriptor libraries list
1836 if($Descriptor{$LibVersion}{"Libs"})
1837 { # multiple descriptors
1838 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1839 }
1840 else {
1841 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1842 }
1843 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1844 {
1845 if(not -e $Path) {
1846 exitStatus("Access_Error", "can't access \'$Path\'");
1847 }
1848 }
1849 }
1850 }
1851 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1852 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001853 if(not -d $Path) {
1854 exitStatus("Access_Error", "can't access directory \'$Path\'");
1855 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001856 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001857 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001858 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001859 }
1860 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1861 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001862 if(not -d $Path) {
1863 exitStatus("Access_Error", "can't access directory \'$Path\'");
1864 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001865 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001866 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001867 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001868 }
1869 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1870 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 if(not -d $Path) {
1872 exitStatus("Access_Error", "can't access directory \'$Path\'");
1873 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001874 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001876 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 $TargetTools{$Path}=1;
1878 }
1879 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1880 $CrossPrefix = $Prefix;
1881 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001882 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1884 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001885 if(not -d $Path) {
1886 exitStatus("Access_Error", "can't access directory \'$Path\'");
1887 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001888 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001890 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001891 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001892 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1894 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001895 if(not -d $Path) {
1896 exitStatus("Access_Error", "can't access directory \'$Path\'");
1897 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001898 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001900 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 }
1902 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001903 { # skip some auto-generated include paths
1904 if(not is_abs($Path))
1905 {
1906 if(my $P = abs_path($Path)) {
1907 $Path = $P;
1908 }
1909 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001910 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
1912 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001913 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 my ($CPath, $Type) = classifyPath($Path);
1915 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
1917 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001918 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1919 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001920 if($Option!~/\A\-(Wl|l|L)/)
1921 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001922 $CompilerOptions{$LibVersion} .= " ".$Option;
1923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001924 }
1925 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1926 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1927 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001928 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 my ($CPath, $Type) = classifyPath($Path);
1930 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001931 }
1932 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1933 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1934 {
1935 my ($CPath, $Type) = classifyPath($Path);
1936 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1937 }
1938 if(my $DDefines = parseTag(\$Content, "defines"))
1939 {
1940 if($Descriptor{$LibVersion}{"Defines"})
1941 { # multiple descriptors
1942 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1943 }
1944 else {
1945 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1946 }
1947 }
1948 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1949 {
1950 if($Order=~/\A(.+):(.+)\Z/) {
1951 $Include_Order{$LibVersion}{$1} = $2;
1952 }
1953 }
1954 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1955 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001956 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001957 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1958 }
1959 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1960 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001961 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001962 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1963 }
1964 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1965 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1966 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001967 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1968 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001970 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1971 $SkipConstants{$LibVersion}{$Constant} = 1;
1972 }
1973 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1974 {
1975 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001976 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001977 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1978 }
1979 else {
1980 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1981 }
1982 }
1983}
1984
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001985sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001986{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001987 my $CodeRef = shift(@_);
1988 my $Tag = shift(@_);
1989 if(not $Tag or not $CodeRef) {
1990 return undef;
1991 }
1992 my $Sp = 0;
1993 if(@_) {
1994 $Sp = shift(@_);
1995 }
1996 my $Start = index(${$CodeRef}, "<$Tag>");
1997 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001998 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001999 my $End = index(${$CodeRef}, "</$Tag>");
2000 if($End!=-1)
2001 {
2002 my $TS = length($Tag)+3;
2003 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2004 substr($Content, 0, $TS-1, ""); # cut start tag
2005 substr($Content, -$TS, $TS, ""); # cut end tag
2006 if(not $Sp)
2007 {
2008 $Content=~s/\A\s+//g;
2009 $Content=~s/\s+\Z//g;
2010 }
2011 if(substr($Content, 0, 1) ne "<") {
2012 $Content = xmlSpecChars_R($Content);
2013 }
2014 return $Content;
2015 }
2016 }
2017 return undef;
2018}
2019
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002020sub getInfo($)
2021{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002022 my $DumpPath = $_[0];
2023 return if(not $DumpPath or not -f $DumpPath);
2024
2025 readTUDump($DumpPath);
2026
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002027 # processing info
2028 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002029
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002030 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002031 setAnonTypedef_All();
2032 }
2033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002034 getTypeInfo_All();
2035 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002036 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002037 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002038 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002040 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002041 %LibInfo = ();
2042 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002043 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002045 %TemplateDecl = ();
2046 %StdCxxTypedef = ();
2047 %MissedTypedef = ();
2048 %Typedef_Tr = ();
2049 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002050 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002051
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002052 # clean cache
2053 delete($Cache{"getTypeAttr"});
2054 delete($Cache{"getTypeDeclId"});
2055
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002056 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002057 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002058 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002059 }
2060 else
2061 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002062 if($BinaryOnly and not $ExtendedCheck)
2063 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002064 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002065 }
2066 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002067 remove_Unused($Version, "Extended");
2068 }
2069 }
2070
2071 if($CheckInfo)
2072 {
2073 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2074 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2075 }
2076
2077 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2078 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002080 }
2081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002082 if($Debug) {
2083 # debugMangling($Version);
2084 }
2085}
2086
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002087sub readTUDump($)
2088{
2089 my $DumpPath = $_[0];
2090
2091 open(TU_DUMP, $DumpPath);
2092 local $/ = undef;
2093 my $Content = <TU_DUMP>;
2094 close(TU_DUMP);
2095
2096 unlink($DumpPath);
2097
2098 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002099 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002100
2101 # clean memory
2102 undef $Content;
2103
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002104 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002105
2106 foreach (0 .. $#Lines)
2107 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002108 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002109 { # get a number and attributes of a node
2110 next if(not $NodeType{$2});
2111 $LibInfo{$Version}{"info_type"}{$1}=$2;
2112 $LibInfo{$Version}{"info"}{$1}=$3;
2113 }
2114
2115 # clean memory
2116 delete($Lines[$_]);
2117 }
2118
2119 # clean memory
2120 undef @Lines;
2121}
2122
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002123sub simplifyConstants()
2124{
2125 foreach my $Constant (keys(%{$Constants{$Version}}))
2126 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002127 if(defined $Constants{$Version}{$Constant}{"Header"})
2128 {
2129 my $Value = $Constants{$Version}{$Constant}{"Value"};
2130 if(defined $EnumConstants{$Version}{$Value}) {
2131 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2132 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002133 }
2134 }
2135}
2136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002137sub simplifyNames()
2138{
2139 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2140 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002141 if($Typedef_Eq{$Version}{$Base}) {
2142 next;
2143 }
2144 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2145 if($#Translations==0)
2146 {
2147 if(length($Translations[0])<=length($Base)) {
2148 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2149 }
2150 }
2151 else
2152 { # select most appropriate
2153 foreach my $Tr (@Translations)
2154 {
2155 if($Base=~/\A\Q$Tr\E/)
2156 {
2157 $Typedef_Eq{$Version}{$Base} = $Tr;
2158 last;
2159 }
2160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002161 }
2162 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002163 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002164 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002165 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002166 if(not $TypeName) {
2167 next;
2168 }
2169 next if(index($TypeName,"<")==-1);# template instances only
2170 if($TypeName=~/>(::\w+)+\Z/)
2171 { # skip unused types
2172 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002173 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002174 foreach my $Base (sort {length($b)<=>length($a)}
2175 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002176 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002177 next if(not $Base);
2178 next if(index($TypeName,$Base)==-1);
2179 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002180 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002181 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002182 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2183 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2184 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002185 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002186 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2187 {
2188 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2189 {
2190 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2191 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002192 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002193 }
2194 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002197 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002198 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002199 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2200 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002201 }
2202}
2203
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002204sub setAnonTypedef_All()
2205{
2206 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2207 {
2208 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2209 {
2210 if(isAnon(getNameByInfo($InfoId))) {
2211 $TypedefToAnon{getTypeId($InfoId)} = 1;
2212 }
2213 }
2214 }
2215}
2216
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002217sub setTemplateParams_All()
2218{
2219 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2220 {
2221 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2222 setTemplateParams($_);
2223 }
2224 }
2225}
2226
2227sub setTemplateParams($)
2228{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002229 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002230 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002231 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002232 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002233 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002234 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002235 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002236 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002237 setTemplateInstParams($_[0], $TmplInst_Id);
2238 }
2239 }
2240
2241 $BasicTemplate{$Version}{$Tid} = $_[0];
2242
2243 if(my $Prms = getTreeAttr_Prms($_[0]))
2244 {
2245 if(my $Valu = getTreeAttr_Valu($Prms))
2246 {
2247 my $Vector = getTreeVec($Valu);
2248 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2249 {
2250 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2251 {
2252 if(my $Name = getNameByInfo($Val))
2253 {
2254 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2255 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2256 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2257 }
2258 else {
2259 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2260 }
2261 }
2262 }
2263 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002265 }
2266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002267 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002268 {
2269 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2270 {
2271 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002272 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002273 }
2274 }
2275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002276}
2277
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002278sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002279{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002280 my ($Tmpl, $Inst) = @_;
2281
2282 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002283 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002284 my ($Params_InfoId, $ElemId) = ();
2285 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2286 $Params_InfoId = $1;
2287 }
2288 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2289 $ElemId = $1;
2290 }
2291 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002292 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002293 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2294 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2295 {
2296 my ($PPos, $PTypeId) = ($1, $2);
2297 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2298 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002299 if($PType eq "template_type_parm") {
2300 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002301 }
2302 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002303 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2304 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002305 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002306 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002307 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002308 else
2309 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002310 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002311 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002313 }
2314 }
2315 }
2316}
2317
2318sub getTypeDeclId($)
2319{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002320 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002321 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002322 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2323 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2324 }
2325 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2326 {
2327 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2328 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002331 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002332 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002333}
2334
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002335sub getTypeInfo_All()
2336{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002337 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002338 { # support for GCC < 4.5
2339 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2340 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2341 # FIXME: check GCC versions
2342 addMissedTypes_Pre();
2343 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002344
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002346 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002347 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2348 if($IType=~/_type\Z/ and $IType ne "function_type"
2349 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002350 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002351 }
2352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002353
2354 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002355 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002356 "Name" => "...",
2357 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002358 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002359 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002360 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002361
2362 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363 { # support for GCC < 4.5
2364 addMissedTypes_Post();
2365 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002366
2367 if($ADD_TMPL_INSTANCES)
2368 {
2369 # templates
2370 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2371 {
2372 if(defined $TemplateMap{$Version}{$Tid}
2373 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2374 {
2375 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2376 {
2377 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2378 {
2379 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2380 {
2381 if(my %MAttr = getTypeAttr($MembTypeId))
2382 {
2383 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2384 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2385 }
2386 }
2387 }
2388 }
2389 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2390 {
2391 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2392 {
2393 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2394
2395 if($NBid ne $Bid)
2396 {
2397 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2398 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2399 }
2400 }
2401 }
2402 }
2403 }
2404 }
2405}
2406
2407sub createType($$)
2408{
2409 my ($Attr, $LibVersion) = @_;
2410 my $NewId = ++$MAX_ID;
2411
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002412 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002413 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002414 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002415
2416 return "$NewId";
2417}
2418
2419sub instType($$$)
2420{ # create template instances
2421 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002422
2423 if(not $TypeInfo{$LibVersion}{$Tid}) {
2424 return undef;
2425 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002426 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2427
2428 foreach my $Key (sort keys(%{$Map}))
2429 {
2430 if(my $Val = $Map->{$Key})
2431 {
2432 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2433
2434 if(defined $Attr->{"NameSpace"}) {
2435 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2436 }
2437 foreach (keys(%{$Attr->{"TParam"}})) {
2438 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2439 }
2440 }
2441 else
2442 { # remove absent
2443 # _Traits, etc.
2444 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002445 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002446 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2447 }
2448 foreach (keys(%{$Attr->{"TParam"}}))
2449 {
2450 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2451 delete($Attr->{"TParam"}{$_});
2452 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002453 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002454 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2455 }
2456 }
2457 }
2458 }
2459
2460 my $Tmpl = 0;
2461
2462 if(defined $Attr->{"TParam"})
2463 {
2464 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2465 {
2466 my $PName = $Attr->{"TParam"}{$_}{"name"};
2467
2468 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2469 {
2470 my %Base = get_BaseType($PTid, $LibVersion);
2471
2472 if($Base{"Type"} eq "TemplateParam"
2473 or defined $Base{"Template"})
2474 {
2475 $Tmpl = 1;
2476 last
2477 }
2478 }
2479 }
2480 }
2481
2482 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2483 return "$Id";
2484 }
2485 else
2486 {
2487 if(not $Tmpl) {
2488 delete($Attr->{"Template"});
2489 }
2490
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002491 my $New = createType($Attr, $LibVersion);
2492
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002493 my %EMap = ();
2494 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2495 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2496 }
2497 foreach (keys(%{$Map})) {
2498 $EMap{$_} = $Map->{$_};
2499 }
2500
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002501 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2502 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002503 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002504 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002505 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002506 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002507 {
2508 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2509
2510 if($NBid ne $Bid)
2511 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002512 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2513 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002514 }
2515 }
2516 }
2517
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002518 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002519 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002520 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2521 {
2522 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2523 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2524 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002525 }
2526 }
2527
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002528 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002530 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2531 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002532 }
2533 }
2534
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002535 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2536 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002537 }
2538
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002539 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002541}
2542
2543sub addMissedTypes_Pre()
2544{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002545 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002546 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2547 { # detecting missed typedefs
2548 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2549 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002550 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002551 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002552 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002553 if($TypeType eq "Unknown")
2554 { # template_type_parm
2555 next;
2556 }
2557 my $TypeDeclId = getTypeDeclId($TypeId);
2558 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2559 my $TypedefName = getNameByInfo($MissedTDid);
2560 next if(not $TypedefName);
2561 next if($TypedefName eq "__float80");
2562 next if(isAnon($TypedefName));
2563 if(not $TypeDeclId
2564 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002565 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002566 }
2567 }
2568 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002569 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002570 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002571 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002572 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002573 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002574 next;
2575 }
2576 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002577 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002578 if(not $TypedefName) {
2579 next;
2580 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002581 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002582 my %MissedInfo = ( # typedef info
2583 "Name" => $TypedefName,
2584 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002585 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002586 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002587 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588 my ($H, $L) = getLocation($MissedTDid);
2589 $MissedInfo{"Header"} = $H;
2590 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002591 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 { # other types
2593 next;
2594 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002595 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002597 next;
2598 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002599 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002601 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002603 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002604 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002605 next;
2606 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002607 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002608 next;
2609 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002610 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 next;
2613 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002614 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 next;
2617 }
2618 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002619
2620 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002623 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002624 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002625 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002627
2628 # add missed & remove other
2629 $TypeInfo{$Version} = \%AddTypes;
2630 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631}
2632
2633sub addMissedTypes_Post()
2634{
2635 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2636 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002637 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2638 {
2639 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2640 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2641 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2642 }
2643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002644 }
2645}
2646
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002647sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002648{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002649 my $TypeId = $_[0];
2650 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2651 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002653 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002655}
2656
2657sub getArraySize($$)
2658{
2659 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002660 if(my $Size = getSize($TypeId))
2661 {
2662 my $Elems = $Size/$BYTE_SIZE;
2663 while($BaseName=~s/\s*\[(\d+)\]//) {
2664 $Elems/=$1;
2665 }
2666 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2667 {
2668 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2669 $Elems/=$BasicSize;
2670 }
2671 }
2672 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002673 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002674 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675}
2676
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002677sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002678{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002679 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002681 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2682 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002684 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2685 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2686 if(not $NodeType)
2687 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002688 return ();
2689 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002690 if($NodeType eq "tree_vec")
2691 {
2692 if($Pos!=$#Positions)
2693 { # select last vector of parameters ( ns<P1>::type<P2> )
2694 next;
2695 }
2696 }
2697 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2698 foreach my $P (@Params)
2699 {
2700 if($P eq "") {
2701 return ();
2702 }
2703 elsif($P ne "\@skip\@") {
2704 @TmplParams = (@TmplParams, $P);
2705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002706 }
2707 }
2708 return @TmplParams;
2709}
2710
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002711sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002713 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002714 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002715 if(defined $TypeInfo{$Version}{$TypeId}
2716 and $TypeInfo{$Version}{$TypeId}{"Name"})
2717 { # already created
2718 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002720 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2721 { # incomplete type
2722 return ();
2723 }
2724 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2725
2726 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002727 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728
2729 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2730 {
2731 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2732 {
2733 if($Info=~/qual[ ]*:/)
2734 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002735 my $NewId = ++$MAX_ID;
2736
2737 $MissedBase{$Version}{$TypeId} = "$NewId";
2738 $MissedBase_R{$Version}{$NewId} = $TypeId;
2739 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2740 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002741 }
2742 }
2743 $TypeAttr{"Type"} = "Typedef";
2744 }
2745 else {
2746 $TypeAttr{"Type"} = getTypeType($TypeId);
2747 }
2748
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002749 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2750 {
2751 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2752 { # local code
2753 return ();
2754 }
2755 }
2756
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002757 if($TypeAttr{"Type"} eq "Unknown") {
2758 return ();
2759 }
2760 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2761 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002762 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002763 if(my $TName = $TypeAttr{"Name"})
2764 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002765 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002766 $TName_Tid{$Version}{$TName} = $TypeId;
2767 return %TypeAttr;
2768 }
2769 else {
2770 return ();
2771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002772 }
2773 elsif($TypeAttr{"Type"} eq "Array")
2774 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002775 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2776 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002777 return ();
2778 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002779 if(my $Algn = getAlgn($TypeId)) {
2780 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2781 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002782 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002783 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002784 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002785 if(not $BTAttr{"Name"}) {
2786 return ();
2787 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002788 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002789 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002790 if(my $Size = getSize($TypeId)) {
2791 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2792 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002793 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002794 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2795 }
2796 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002797 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002799 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002800 else
2801 {
2802 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002803 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002804 $TypeAttr{"Name"} = $1."[]".$2;
2805 }
2806 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002807 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002809 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002810 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002811 if($BTAttr{"Header"}) {
2812 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002813 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002814 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002815 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2816 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002818 return ();
2819 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002820 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002822 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002823 if($TypeAttr{"Name"})
2824 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002825 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002826
2827 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2828 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002829 { # NOTE: register only one int: with built-in decl
2830 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2831 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2832 }
2833 }
2834 return %TypeAttr;
2835 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002836 else {
2837 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002839 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002840 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2841 {
2842 %TypeAttr = getTrivialTypeAttr($TypeId);
2843 if($TypeAttr{"Name"})
2844 {
2845 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2846 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2847 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2848 }
2849 return %TypeAttr;
2850 }
2851 else {
2852 return ();
2853 }
2854 }
2855 elsif($TypeAttr{"Type"} eq "SizeOf")
2856 {
2857 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2858 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2859 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2860 if($TypeAttr{"Name"})
2861 {
2862 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2863 return %TypeAttr;
2864 }
2865 else {
2866 return ();
2867 }
2868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002869 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002870 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002871 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2872 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002873 return ();
2874 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002875 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002876 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002877 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002879 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002881 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 }
2884 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002885 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002886 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002887 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002888 return ();
2889 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002890 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002891 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002892 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002893 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002894 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002895 }
2896 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002897 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 {
2899 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002900 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002901 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002902 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2904 }
2905 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002906 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002907 }
2908 }
2909 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002910 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002911 }
2912 if($TypeAttr{"Type"} eq "Typedef")
2913 {
2914 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002915
2916 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2917 return ();
2918 }
2919
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002920 if(isAnon($TypeAttr{"Name"}))
2921 { # anon typedef to anon type: ._N
2922 return ();
2923 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002924
2925 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2926 { # artificial typedef of "struct X" to "X"
2927 $TypeAttr{"Artificial"} = 1;
2928 }
2929
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002930 if(my $NS = getNameSpace($TypeDeclId))
2931 {
2932 my $TypeName = $TypeAttr{"Name"};
2933 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2934 { # "some_type" is the typedef to "struct some_type" in C++
2935 if($3) {
2936 $TypeAttr{"Name"} = $3."::".$TypeName;
2937 }
2938 }
2939 else
2940 {
2941 $TypeAttr{"NameSpace"} = $NS;
2942 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002943
2944 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2945 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2946 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002947 if($BTAttr{"NameSpace"}
2948 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002949 { # types like "std::fpos<__mbstate_t>" are
2950 # not covered by typedefs in the TU dump
2951 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002952 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2953 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002954 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002956 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002957 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002959 }
2960 }
2961 }
2962 }
2963 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002964 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002966 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002967 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2968 { # typedef int*const TYPEDEF; // first
2969 # int foo(TYPEDEF p); // const is optimized out
2970 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2971 if($BTAttr{"Name"}=~/</)
2972 {
2973 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2974 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 }
2977 }
2978 }
2979 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2980 }
2981 if(not $TypeAttr{"Size"})
2982 {
2983 if($TypeAttr{"Type"} eq "Pointer") {
2984 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2985 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002986 elsif($BTAttr{"Size"}) {
2987 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002988 }
2989 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002990 if(my $Algn = getAlgn($TypeId)) {
2991 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2992 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002993 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002994 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2995 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002996 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002997 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002998 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002999 { # typedef to "class Class"
3000 # should not be registered in TName_Tid
3001 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3002 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003004 }
3005 return %TypeAttr;
3006 }
3007}
3008
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003009sub getTreeVec($)
3010{
3011 my %Vector = ();
3012 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3013 {
3014 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3015 { # string length is N-1 because of the null terminator
3016 $Vector{$1} = $2;
3017 }
3018 }
3019 return \%Vector;
3020}
3021
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003022sub get_TemplateParam($$)
3023{
3024 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003025 return () if(not $Type_Id);
3026 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3027 return () if(not $NodeType);
3028 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003029 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003030 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003031 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032 my $Num = getNodeIntCst($Type_Id);
3033 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003034 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003035 }
3036 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003037 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003038 }
3039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003040 elsif($NodeType eq "string_cst") {
3041 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003043 elsif($NodeType eq "tree_vec")
3044 {
3045 my $Vector = getTreeVec($Type_Id);
3046 my @Params = ();
3047 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3048 {
3049 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3050 push(@Params, $P2);
3051 }
3052 }
3053 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003054 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003055 elsif($NodeType eq "parm_decl")
3056 {
3057 (getNameByInfo($Type_Id));
3058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003059 else
3060 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003061 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003062 my $PName = $ParamAttr{"Name"};
3063 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003064 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003066 if($PName=~/\>/)
3067 {
3068 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 $PName = $Cover;
3070 }
3071 }
3072 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003073 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3075 # template<typename _Key, typename _Compare = std::less<_Key>
3076 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3077 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3078 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3079 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003080 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003082 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003083 }
3084}
3085
3086sub cover_stdcxx_typedef($)
3087{
3088 my $TypeName = $_[0];
3089 if(my @Covers = sort {length($a)<=>length($b)}
3090 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3091 { # take the shortest typedef
3092 # FIXME: there may be more than
3093 # one typedefs to the same type
3094 return $Covers[0];
3095 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003096 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3098 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3099 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003100 if(my $Cover = $Covers[0])
3101 {
3102 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3103 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003105 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003106 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003107}
3108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003109sub getNodeIntCst($)
3110{
3111 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003112 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003113 if($EnumMembName_Id{$Version}{$CstId}) {
3114 return $EnumMembName_Id{$Version}{$CstId};
3115 }
3116 elsif((my $Value = getTreeValue($CstId)) ne "")
3117 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003118 if($Value eq "0")
3119 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003120 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003121 return "false";
3122 }
3123 else {
3124 return "0";
3125 }
3126 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003127 elsif($Value eq "1")
3128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003129 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003130 return "true";
3131 }
3132 else {
3133 return "1";
3134 }
3135 }
3136 else {
3137 return $Value;
3138 }
3139 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003140 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003141}
3142
3143sub getNodeStrCst($)
3144{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003145 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3146 {
3147 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003148 {
3149 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3150 { # string length is N-1 because of the null terminator
3151 return substr($1, 0, $2-1);
3152 }
3153 else
3154 { # identifier_node
3155 return substr($1, 0, $2);
3156 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003157 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003159 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003160}
3161
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003162sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003164 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003165 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3166 if($Type eq "FieldPtr") {
3167 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3168 }
3169 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3170 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003171 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003172 if($Type eq "MethodPtr")
3173 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003174 if(my $Size = getSize($TypeId))
3175 {
3176 $Size/=$BYTE_SIZE;
3177 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003179 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003180 if(my $Algn = getAlgn($TypeId)) {
3181 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003183 # Return
3184 if($Type eq "FieldPtr")
3185 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003186 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003187 if($ReturnAttr{"Name"}) {
3188 $MemPtrName .= $ReturnAttr{"Name"};
3189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003190 $TypeAttr{"Return"} = $PtrId;
3191 }
3192 else
3193 {
3194 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3195 {
3196 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3198 if(not $ReturnAttr{"Name"})
3199 { # templates
3200 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003201 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003202 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003203 $TypeAttr{"Return"} = $ReturnTypeId;
3204 }
3205 }
3206 # Class
3207 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3208 {
3209 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003210 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003211 if($Class{"Name"}) {
3212 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3213 }
3214 else {
3215 $MemPtrName .= " (*)";
3216 }
3217 }
3218 else {
3219 $MemPtrName .= " (*)";
3220 }
3221 # Parameters
3222 if($Type eq "FuncPtr"
3223 or $Type eq "MethodPtr")
3224 {
3225 my @ParamTypeName = ();
3226 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3227 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003228 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003229 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003230 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003231 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003232 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3233 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003234 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003235 my $PTypeId = $1;
3236 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003237 if(not $ParamAttr{"Name"})
3238 { # templates (template_type_parm), etc.
3239 return ();
3240 }
3241 if($ParamAttr{"Name"} eq "void") {
3242 last;
3243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003244 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003245 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003246 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003247 push(@ParamTypeName, $ParamAttr{"Name"});
3248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003249 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3250 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 }
3252 else {
3253 last;
3254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003255 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003256 else {
3257 last;
3258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259 }
3260 }
3261 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3262 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003263 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003264 return %TypeAttr;
3265}
3266
3267sub getTreeTypeName($)
3268{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003269 my $TypeId = $_[0];
3270 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003271 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003272 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003273 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003274 if(my $Name = getNameByInfo($TypeId))
3275 { # bit_size_type
3276 return $Name;
3277 }
3278 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003279 return "unsigned int";
3280 }
3281 else {
3282 return "int";
3283 }
3284 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003285 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003286 return getNameByInfo($1);
3287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003289 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003290}
3291
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003293{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003294 my $Ptd = pointTo($_[0]);
3295 return 0 if(not $Ptd);
3296 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003298 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3299 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003300 }
3301 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3303 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003304 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003305 if($InfoT1 eq "pointer_type"
3306 and $InfoT2 eq "function_type") {
3307 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308 }
3309 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003310 return 0;
3311}
3312
3313sub isMethodPtr($)
3314{
3315 my $Ptd = pointTo($_[0]);
3316 return 0 if(not $Ptd);
3317 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3318 {
3319 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3320 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3321 and $Info=~/ ptrmem /) {
3322 return 1;
3323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003324 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003325 return 0;
3326}
3327
3328sub isFieldPtr($)
3329{
3330 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3331 {
3332 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3333 and $Info=~/ ptrmem /) {
3334 return 1;
3335 }
3336 }
3337 return 0;
3338}
3339
3340sub pointTo($)
3341{
3342 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3343 {
3344 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3345 return $1;
3346 }
3347 }
3348 return "";
3349}
3350
3351sub getTypeTypeByTypeId($)
3352{
3353 my $TypeId = $_[0];
3354 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3355 {
3356 my $NType = $NodeType{$TType};
3357 if($NType eq "Intrinsic") {
3358 return $NType;
3359 }
3360 elsif(isFuncPtr($TypeId)) {
3361 return "FuncPtr";
3362 }
3363 elsif(isMethodPtr($TypeId)) {
3364 return "MethodPtr";
3365 }
3366 elsif(isFieldPtr($TypeId)) {
3367 return "FieldPtr";
3368 }
3369 elsif($NType ne "Other") {
3370 return $NType;
3371 }
3372 }
3373 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003374}
3375
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003376my %UnQual = (
3377 "r"=>"restrict",
3378 "v"=>"volatile",
3379 "c"=>"const",
3380 "cv"=>"const volatile"
3381);
3382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003383sub getQual($)
3384{
3385 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003386 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3387 {
3388 my ($Qual, $To) = ();
3389 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3390 $Qual = $UnQual{$1};
3391 }
3392 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3393 $To = $1;
3394 }
3395 if($Qual and $To) {
3396 return ($Qual, $To);
3397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003398 }
3399 return ();
3400}
3401
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003402sub getQualType($)
3403{
3404 if($_[0] eq "const volatile") {
3405 return "ConstVolatile";
3406 }
3407 return ucfirst($_[0]);
3408}
3409
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003410sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003411{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003412 my $TypeId = $_[0];
3413 my $TypeDeclId = getTypeDeclId($TypeId);
3414 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003415 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003416 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3417 return "Typedef";
3418 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003419 }
3420 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3421 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003422 if(($Qual or $To) and $TypeDeclId
3423 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003424 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003425 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003426 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003427 elsif(not $MissedBase_R{$Version}{$TypeId}
3428 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003429 return "Typedef";
3430 }
3431 elsif($Qual)
3432 { # qualified types
3433 return getQualType($Qual);
3434 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003435
3436 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3437 { # typedef struct { ... } name
3438 $TypeTypedef{$Version}{$TypeId} = $1;
3439 }
3440
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003441 my $TypeType = getTypeTypeByTypeId($TypeId);
3442 if($TypeType eq "Struct")
3443 {
3444 if($TypeDeclId
3445 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3446 return "Template";
3447 }
3448 }
3449 return $TypeType;
3450}
3451
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003452sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003453{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003454 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003455 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003456 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3457 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3458 return 0;
3459 }
3460 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3461 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003462 if(my $TDid = getTypeDeclId($_[0]))
3463 {
3464 if(getTypeId($TDid) eq $_[0]
3465 and getNameByInfo($TDid))
3466 {
3467 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3468 return $1;
3469 }
3470 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003472 }
3473 }
3474 return 0;
3475}
3476
3477sub selectBaseType($)
3478{
3479 my $TypeId = $_[0];
3480 if(defined $MissedTypedef{$Version}{$TypeId})
3481 { # add missed typedefs
3482 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3483 return ($TypeId, "");
3484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003485 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003486 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3487 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003488
3489 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3490 my $MB = $MissedBase{$Version}{$TypeId};
3491
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003492 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003493 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003494 and (getTypeId($1) ne $TypeId)
3495 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003496 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003497 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003499 elsif($MB)
3500 { # add base
3501 return ($MB, "");
3502 }
3503 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003504 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003505 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003506 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003507 elsif($Qual or $To)
3508 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003511 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003512 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003513 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003514 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003517 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003518 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003519 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003520 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003524 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003525 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003526 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003529
3530 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003531}
3532
3533sub getSymbolInfo_All()
3534{
3535 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3536 { # reverse order
3537 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003538 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003539 }
3540 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003541
3542 if($ADD_TMPL_INSTANCES)
3543 {
3544 # templates
3545 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3546 {
3547 my %Map = ();
3548
3549 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3550 {
3551 if(defined $TemplateMap{$Version}{$ClassId})
3552 {
3553 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3554 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3555 }
3556 }
3557 }
3558
3559 if(defined $TemplateMap{$Version}{$Sid})
3560 {
3561 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3562 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3563 }
3564 }
3565
3566 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3567 {
3568 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3569 {
3570 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3571 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3572 }
3573 }
3574 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3575 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3576 }
3577 }
3578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003579}
3580
3581sub getVarInfo_All()
3582{
3583 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3584 { # reverse order
3585 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003586 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003587 }
3588 }
3589}
3590
3591sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003592 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003593}
3594
3595sub getVarInfo($)
3596{
3597 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003598 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003599 {
3600 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3601 if($NSInfoType and $NSInfoType eq "function_decl") {
3602 return;
3603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003604 }
3605 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3606 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3607 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3608 delete($SymbolInfo{$Version}{$InfoId});
3609 return;
3610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003611 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003612 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003613 delete($SymbolInfo{$Version}{$InfoId});
3614 return;
3615 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003616 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3617 delete($SymbolInfo{$Version}{$InfoId});
3618 return;
3619 }
3620 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003621 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3622 {
3623 if($OSgroup eq "windows")
3624 { # cut the offset
3625 $MnglName=~s/\@\d+\Z//g;
3626 }
3627 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003629 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003630 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003631 { # validate mangled name
3632 delete($SymbolInfo{$Version}{$InfoId});
3633 return;
3634 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003635 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003636 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003637 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003638 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003639 }
3640 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3641 { # non-public global data
3642 delete($SymbolInfo{$Version}{$InfoId});
3643 return;
3644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003645 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003646 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003647 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003648 if(not defined $TypeInfo{$Version}{$Rid}
3649 or not $TypeInfo{$Version}{$Rid}{"Name"})
3650 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003651 delete($SymbolInfo{$Version}{$InfoId});
3652 return;
3653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003654 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3655 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003656 if(defined $Val) {
3657 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003659 }
3660 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3662 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003663 if(not defined $TypeInfo{$Version}{$ClassId}
3664 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3665 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003666 delete($SymbolInfo{$Version}{$InfoId});
3667 return;
3668 }
3669 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003670 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3671 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003672 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003673 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003674 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003675 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003676 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003677 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003678 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003679 if(not $CheckHeadersOnly)
3680 {
3681 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3682 {
3683 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3684 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3685 {
3686 if(link_symbol($ShortName, $Version, "-Deps"))
3687 { # "const" global data is mangled as _ZL... in the TU dump
3688 # but not mangled when compiling a C shared library
3689 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3690 }
3691 }
3692 }
3693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 if($COMMON_LANGUAGE{$Version} eq "C++")
3695 {
3696 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3697 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003698 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003699 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3700 }
3701 }
3702 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3703 { # try to mangle symbol (link with libraries)
3704 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3705 }
3706 if($OStarget eq "windows")
3707 {
3708 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3709 { # link MS C++ symbols from library with GCC symbols from headers
3710 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3711 }
3712 }
3713 }
3714 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3715 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3716 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003717 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3718 {
3719 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3720 { # non-target symbols
3721 delete($SymbolInfo{$Version}{$InfoId});
3722 return;
3723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003724 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003725 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3726 {
3727 if(defined $MissedTypedef{$Version}{$Rid})
3728 {
3729 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3730 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3731 }
3732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003733 }
3734 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003735 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3737 }
3738 if($ShortName=~/\A(_Z|\?)/) {
3739 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3740 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003741
3742 if($ExtraDump) {
3743 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003745}
3746
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003747sub isConstType($$)
3748{
3749 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003750 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003751 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003752 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003753 }
3754 return ($Base{"Type"} eq "Const");
3755}
3756
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003757sub getTrivialName($$)
3758{
3759 my ($TypeInfoId, $TypeId) = @_;
3760 my %TypeAttr = ();
3761 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3762 if(not $TypeAttr{"Name"}) {
3763 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3764 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003765 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003766 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003767 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003768 if(isAnon($TypeAttr{"Name"}))
3769 {
3770 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003771 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003772 { # searching for a first not anon scope
3773 if($NSId eq $NameSpaceId) {
3774 last;
3775 }
3776 else
3777 {
3778 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3779 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003780 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003781 last;
3782 }
3783 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003784 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003785 }
3786 }
3787 else
3788 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003789 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003790 {
3791 if($NameSpaceId ne $TypeId) {
3792 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003794 }
3795 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003796 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3798 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003799 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003800 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003801 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003802 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003803 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003804 if($TypeAttr{"NameSpace"}) {
3805 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003807 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003808 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3809 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003810 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003811 if(my @TParams = getTParams($TypeId, "Type")) {
3812 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3813 }
3814 else {
3815 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817 }
3818 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3819}
3820
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003821sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003822{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003823 my $TypeId = $_[0];
3824 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003825
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003826 my %TypeAttr = ();
3827
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003828 if($TemplateDecl{$Version}{$TypeId})
3829 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003830 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003831 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003832
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003833 setTypeAccess($TypeId, \%TypeAttr);
3834 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3835 if(isBuiltIn($TypeAttr{"Header"}))
3836 {
3837 delete($TypeAttr{"Header"});
3838 delete($TypeAttr{"Line"});
3839 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003840
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003841 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003842 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3843 if(not $TypeAttr{"Name"}) {
3844 return ();
3845 }
3846 if(not $TypeAttr{"NameSpace"}) {
3847 delete($TypeAttr{"NameSpace"});
3848 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003849
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003850 if($TypeAttr{"Type"} eq "Intrinsic")
3851 {
3852 if(defined $TypeAttr{"Header"})
3853 {
3854 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3855 { # support for SUSE 11.2
3856 # integer_type has srcp dump{1-2}.i
3857 delete($TypeAttr{"Header"});
3858 }
3859 }
3860 }
3861
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003862 my $Tmpl = undef;
3863
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003864 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003865 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003866 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3867
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003868 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003869 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003870 foreach my $Pos (0 .. $#TParams)
3871 {
3872 my $Val = $TParams[$Pos];
3873 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3874
3875 if(not defined $TypeAttr{"Template"})
3876 {
3877 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3878
3879 if($Base{"Type"} eq "TemplateParam"
3880 or defined $Base{"Template"}) {
3881 $TypeAttr{"Template"} = 1;
3882 }
3883 }
3884
3885 if($Tmpl)
3886 {
3887 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3888 {
3889 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3890
3891 if($Val eq $Arg) {
3892 $TypeAttr{"Template"} = 1;
3893 }
3894 }
3895 }
3896 }
3897
3898 if($Tmpl)
3899 {
3900 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3901 {
3902 if($Pos>$#TParams)
3903 {
3904 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3905 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3906 }
3907 }
3908 }
3909 }
3910
3911 if($ADD_TMPL_INSTANCES)
3912 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003913 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003914 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003915 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003916 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003917 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003918 {
3919 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3920 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3921 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003922 }
3923 if(not getTreeAttr_Binf($TypeId))
3924 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003925 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3926 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3927 }
3928 }
3929 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003930 }
3931 }
3932 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003933
3934 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3935
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003936 if(my $Size = getSize($TypeId))
3937 {
3938 $Size = $Size/$BYTE_SIZE;
3939 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003940 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003941 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003942 {
3943 if($ExtraDump)
3944 {
3945 if(not defined $TypeAttr{"Memb"}
3946 and not $Tmpl)
3947 { # declaration only
3948 $TypeAttr{"Forward"} = 1;
3949 }
3950 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003951 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003953 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003954 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003955 {
3956 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003957 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003958 }
3959 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003960 or $TypeAttr{"Type"} eq "Class")
3961 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003962 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003963 if($Skip) {
3964 return ();
3965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003966 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003967 if(my $Algn = getAlgn($TypeId)) {
3968 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003971
3972 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3973 {
3974 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003975 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003976 {
3977 if(not isAnon($TypeAttr{"Name"})) {
3978 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3979 }
3980 }
3981 }
3982
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003983 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003984 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3985 {
3986 my @Entries = split(/\n/, $VTable);
3987 foreach (1 .. $#Entries)
3988 {
3989 my $Entry = $Entries[$_];
3990 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003991 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003992 }
3993 }
3994 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003995
3996 if($TypeAttr{"Type"} eq "Enum")
3997 {
3998 if(not $TypeAttr{"NameSpace"})
3999 {
4000 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4001 {
4002 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004003 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004004 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004005 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004006 "Header"=>$TypeAttr{"Header"}
4007 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004008 if(isAnon($TypeAttr{"Name"}))
4009 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004010 if($ExtraDump
4011 or is_target_header($TypeAttr{"Header"}, $Version))
4012 {
4013 %{$Constants{$Version}{$MName}} = (
4014 "Value" => $MVal,
4015 "Header" => $TypeAttr{"Header"}
4016 );
4017 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004018 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004019 }
4020 }
4021 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004022 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004023 {
4024 if(defined $TypedefToAnon{$TypeId}) {
4025 $TypeAttr{"AnonTypedef"} = 1;
4026 }
4027 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004028
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004029 return %TypeAttr;
4030}
4031
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004032sub simplifyVTable($)
4033{
4034 my $Content = $_[0];
4035 if($Content=~s/ \[with (.+)]//)
4036 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4037 if(my @Elems = separate_Params($1, 0, 0))
4038 {
4039 foreach my $Elem (@Elems)
4040 {
4041 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4042 {
4043 my ($Arg, $Val) = ($1, $2);
4044
4045 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4046 $Content=~s/,\s*$Arg\b//g;
4047 }
4048 else {
4049 $Content=~s/\b$Arg\b/$Val/g;
4050 }
4051 }
4052 }
4053 }
4054 }
4055
4056 return $Content;
4057}
4058
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004059sub detect_lang($)
4060{
4061 my $TypeId = $_[0];
4062 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004063 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004064 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004065 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4066 }
4067 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004068 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004069 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004070 while($Fncs)
4071 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004072 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004073 return 1;
4074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004075 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004076 }
4077 }
4078 return 0;
4079}
4080
4081sub setSpec($$)
4082{
4083 my ($TypeId, $TypeAttr) = @_;
4084 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4085 if($Info=~/\s+spec\s+/) {
4086 $TypeAttr->{"Spec"} = 1;
4087 }
4088}
4089
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004090sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004091{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004092 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004094 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004095 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004096 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004097 my $Pos = 0;
4098 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4099 {
4100 my ($Access, $BInfoId) = ($1, $2);
4101 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004102
4103 if($ClassId==$TypeId)
4104 { # class A<N>:public A<N-1>
4105 next;
4106 }
4107
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004108 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4109 if(not $CType or $CType eq "template_type_parm"
4110 or $CType eq "typename_type")
4111 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004112 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004114 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004115 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4117 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004118 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4120 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004121 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004123 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004124 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4125 }
4126 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004127 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004128 }
4129 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004130 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004131}
4132
4133sub getBinfClassId($)
4134{
4135 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4136 $Info=~/type[ ]*:[ ]*@(\d+) /;
4137 return $1;
4138}
4139
4140sub unmangledFormat($$)
4141{
4142 my ($Name, $LibVersion) = @_;
4143 $Name = uncover_typedefs($Name, $LibVersion);
4144 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4145 $Name=~s/\(\w+\)(\d)/$1/;
4146 return $Name;
4147}
4148
4149sub modelUnmangled($$)
4150{
4151 my ($InfoId, $Compiler) = @_;
4152 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4153 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4154 }
4155 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4156 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4157 $PureSignature = "~".$PureSignature;
4158 }
4159 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4160 {
4161 my (@Params, @ParamTypes) = ();
4162 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4163 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4164 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4165 }
4166 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4167 { # checking parameters
4168 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004169 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004170 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004171 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004172
4173 if($PName eq "this"
4174 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4175 {
4176 next;
4177 }
4178
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004179 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004180 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004181 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004182 }
4183 @ParamTypes = (@ParamTypes, $PTName);
4184 }
4185 if(@ParamTypes) {
4186 $PureSignature .= "(".join(", ", @ParamTypes).")";
4187 }
4188 else
4189 {
4190 if($Compiler eq "MSVC")
4191 {
4192 $PureSignature .= "(void)";
4193 }
4194 else
4195 { # GCC
4196 $PureSignature .= "()";
4197 }
4198 }
4199 $PureSignature = delete_keywords($PureSignature);
4200 }
4201 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4202 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004203 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004204 $PureSignature = $ClassName."::".$PureSignature;
4205 }
4206 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4207 $PureSignature = $NS."::".$PureSignature;
4208 }
4209 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4210 $PureSignature .= " const";
4211 }
4212 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4213 $PureSignature .= " volatile";
4214 }
4215 my $ShowReturn = 0;
4216 if($Compiler eq "MSVC"
4217 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4218 {
4219 $ShowReturn=1;
4220 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004221 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4222 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004223 {
4224 $ShowReturn=1;
4225 }
4226 if($ShowReturn)
4227 { # mangled names for template function specializations include return value
4228 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4229 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004230 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004231 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4232 $PureSignature = $ReturnName." ".$PureSignature;
4233 }
4234 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004235 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004236}
4237
4238sub mangle_symbol($$$)
4239{ # mangling for simple methods
4240 # see gcc-4.6.0/gcc/cp/mangle.c
4241 my ($InfoId, $LibVersion, $Compiler) = @_;
4242 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4243 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4244 }
4245 my $Mangled = "";
4246 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004247 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004248 }
4249 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004250 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004251 }
4252 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4253}
4254
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004255sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004256{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257 my ($InfoId, $LibVersion) = @_;
4258 return "";
4259}
4260
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004261sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004262{ # see gcc-4.6.0/gcc/cp/mangle.c
4263 my ($InfoId, $LibVersion) = @_;
4264 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004265 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004266 my %Repl = ();# SN_ replacements
4267 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4268 {
4269 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4270 if($MangledClass!~/\AN/) {
4271 $MangledClass = "N".$MangledClass;
4272 }
4273 else {
4274 $MangledClass=~s/E\Z//;
4275 }
4276 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4277 $MangledClass=~s/\AN/NV/;
4278 }
4279 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4280 $MangledClass=~s/\AN/NK/;
4281 }
4282 $Mangled .= $MangledClass;
4283 }
4284 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4285 { # mangled by name due to the absence of structured info
4286 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4287 if($MangledNS!~/\AN/) {
4288 $MangledNS = "N".$MangledNS;
4289 }
4290 else {
4291 $MangledNS=~s/E\Z//;
4292 }
4293 $Mangled .= $MangledNS;
4294 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004295 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004296 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004297 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004298 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004299 foreach (@TPos) {
4300 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4301 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004302 }
4303 elsif($TmplParams)
4304 { # remangling mode
4305 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004306 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004307 }
4308 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4309 $Mangled .= "C1";
4310 }
4311 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4312 $Mangled .= "D0";
4313 }
4314 elsif($ShortName)
4315 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004316 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4317 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004318 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004319 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004320 { # "const" global data is mangled as _ZL...
4321 $Mangled .= "L";
4322 }
4323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004324 if($ShortName=~/\Aoperator(\W.*)\Z/)
4325 {
4326 my $Op = $1;
4327 $Op=~s/\A[ ]+//g;
4328 if(my $OpMngl = $OperatorMangling{$Op}) {
4329 $Mangled .= $OpMngl;
4330 }
4331 else { # conversion operator
4332 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4333 }
4334 }
4335 else {
4336 $Mangled .= length($ShortName).$ShortName;
4337 }
4338 if(@TParams)
4339 { # templates
4340 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004341 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004342 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4343 }
4344 $Mangled .= "E";
4345 }
4346 if(not $ClassId and @TParams) {
4347 add_substitution($ShortName, \%Repl, 0);
4348 }
4349 }
4350 if($ClassId or $NameSpace) {
4351 $Mangled .= "E";
4352 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004353 if(@TParams)
4354 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004355 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004356 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4357 }
4358 }
4359 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4360 {
4361 my @Params = ();
4362 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4363 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4364 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4365 }
4366 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4367 { # checking parameters
4368 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4369 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4370 }
4371 if(not @Params) {
4372 $Mangled .= "v";
4373 }
4374 }
4375 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4376 $Mangled = write_stdcxx_substitution($Mangled);
4377 if($Mangled eq "_Z") {
4378 return "";
4379 }
4380 return $Mangled;
4381}
4382
4383sub correct_incharge($$$)
4384{
4385 my ($InfoId, $LibVersion, $Mangled) = @_;
4386 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4387 {
4388 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004389 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004390 }
4391 }
4392 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4393 {
4394 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004395 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004396 }
4397 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004398 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004399 }
4400 }
4401 return $Mangled;
4402}
4403
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004404sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004405{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004406 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004407 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004408 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409 return $Name;
4410 }
4411 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004412 while(my $CPos = find_center($TParams, "<"))
4413 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004414 $TParams = substr($TParams, $CPos);
4415 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004416 if($TParams=~s/\A<(.+)>\Z/$1/) {
4417 $Name=~s/<\Q$TParams\E>\Z//;
4418 }
4419 else
4420 { # error
4421 $TParams = "";
4422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004423 return ($Name, $TParams);
4424}
4425
4426sub get_sub_ns($)
4427{
4428 my $Name = $_[0];
4429 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004430 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004431 {
4432 push(@NS, substr($Name, 0, $CPos));
4433 $Name = substr($Name, $CPos);
4434 $Name=~s/\A:://;
4435 }
4436 return (join("::", @NS), $Name);
4437}
4438
4439sub mangle_ns($$$)
4440{
4441 my ($Name, $LibVersion, $Repl) = @_;
4442 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4443 {
4444 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4445 $Mangled=~s/\AN(.+)E\Z/$1/;
4446 return $Mangled;
4447
4448 }
4449 else
4450 {
4451 my ($MangledNS, $SubNS) = ("", "");
4452 ($SubNS, $Name) = get_sub_ns($Name);
4453 if($SubNS) {
4454 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4455 }
4456 $MangledNS .= length($Name).$Name;
4457 add_substitution($MangledNS, $Repl, 0);
4458 return $MangledNS;
4459 }
4460}
4461
4462sub mangle_param($$$)
4463{
4464 my ($PTid, $LibVersion, $Repl) = @_;
4465 my ($MPrefix, $Mangled) = ("", "");
4466 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004467 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004468 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004469 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004470 if(not $BaseType_Name) {
4471 return "";
4472 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004473 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004474 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004475 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4476 while($Suffix=~/(&|\*|const)\Z/)
4477 {
4478 if($Suffix=~s/[ ]*&\Z//) {
4479 $MPrefix .= "R";
4480 }
4481 if($Suffix=~s/[ ]*\*\Z//) {
4482 $MPrefix .= "P";
4483 }
4484 if($Suffix=~s/[ ]*const\Z//)
4485 {
4486 if($MPrefix=~/R|P/
4487 or $Suffix=~/&|\*/) {
4488 $MPrefix .= "K";
4489 }
4490 }
4491 if($Suffix=~s/[ ]*volatile\Z//) {
4492 $MPrefix .= "V";
4493 }
4494 #if($Suffix=~s/[ ]*restrict\Z//) {
4495 #$MPrefix .= "r";
4496 #}
4497 }
4498 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4499 $Mangled .= $Token;
4500 }
4501 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4502 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004503 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004504 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004505 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004506 foreach (@TPos) {
4507 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4508 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004509 }
4510 elsif($TmplParams)
4511 { # remangling mode
4512 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004513 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004514 }
4515 my $MangledNS = "";
4516 my ($SubNS, $SName) = get_sub_ns($ShortName);
4517 if($SubNS) {
4518 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4519 }
4520 $MangledNS .= length($SName).$SName;
4521 if(@TParams) {
4522 add_substitution($MangledNS, $Repl, 0);
4523 }
4524 $Mangled .= "N".$MangledNS;
4525 if(@TParams)
4526 { # templates
4527 $Mangled .= "I";
4528 foreach my $TParam (@TParams) {
4529 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4530 }
4531 $Mangled .= "E";
4532 }
4533 $Mangled .= "E";
4534 }
4535 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4536 {
4537 if($BaseType{"Type"} eq "MethodPtr") {
4538 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4539 }
4540 else {
4541 $Mangled .= "PF";
4542 }
4543 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4544 my @Params = keys(%{$BaseType{"Param"}});
4545 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4546 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4547 }
4548 if(not @Params) {
4549 $Mangled .= "v";
4550 }
4551 $Mangled .= "E";
4552 }
4553 elsif($BaseType{"Type"} eq "FieldPtr")
4554 {
4555 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4556 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4557 }
4558 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4559 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4560 {
4561 if($Mangled eq $Optimized)
4562 {
4563 if($ShortName!~/::/)
4564 { # remove "N ... E"
4565 if($MPrefix) {
4566 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4567 }
4568 else {
4569 $Mangled=~s/\AN(.+)E\Z/$1/g;
4570 }
4571 }
4572 }
4573 else {
4574 $Mangled = $Optimized;
4575 }
4576 }
4577 add_substitution($Mangled, $Repl, 1);
4578 return $Mangled;
4579}
4580
4581sub mangle_template_param($$$)
4582{ # types + literals
4583 my ($TParam, $LibVersion, $Repl) = @_;
4584 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4585 return mangle_param($TPTid, $LibVersion, $Repl);
4586 }
4587 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4588 { # class_name<1u>::method(...)
4589 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4590 }
4591 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4592 { # class_name<(signed char)1>::method(...)
4593 return "L".$IntrinsicMangling{$1}.$2."E";
4594 }
4595 elsif($TParam eq "true")
4596 { # class_name<true>::method(...)
4597 return "Lb1E";
4598 }
4599 elsif($TParam eq "false")
4600 { # class_name<true>::method(...)
4601 return "Lb0E";
4602 }
4603 else { # internal error
4604 return length($TParam).$TParam;
4605 }
4606}
4607
4608sub add_substitution($$$)
4609{
4610 my ($Value, $Repl, $Rec) = @_;
4611 if($Rec)
4612 { # subtypes
4613 my @Subs = ($Value);
4614 while($Value=~s/\A(R|P|K)//) {
4615 push(@Subs, $Value);
4616 }
4617 foreach (reverse(@Subs)) {
4618 add_substitution($_, $Repl, 0);
4619 }
4620 return;
4621 }
4622 return if($Value=~/\AS(\d*)_\Z/);
4623 $Value=~s/\AN(.+)E\Z/$1/g;
4624 return if(defined $Repl->{$Value});
4625 return if(length($Value)<=1);
4626 return if($StdcxxMangling{$Value});
4627 # check for duplicates
4628 my $Base = $Value;
4629 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4630 {
4631 my $Num = $Repl->{$Type};
4632 my $Replace = macro_mangle($Num);
4633 $Base=~s/\Q$Replace\E/$Type/;
4634 }
4635 if(my $OldNum = $Repl->{$Base})
4636 {
4637 $Repl->{$Value} = $OldNum;
4638 return;
4639 }
4640 my @Repls = sort {$b<=>$a} values(%{$Repl});
4641 if(@Repls) {
4642 $Repl->{$Value} = $Repls[0]+1;
4643 }
4644 else {
4645 $Repl->{$Value} = -1;
4646 }
4647 # register duplicates
4648 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004649 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004650 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4651 {
4652 next if($Base eq $Type);
4653 my $Num = $Repl->{$Type};
4654 my $Replace = macro_mangle($Num);
4655 $Base=~s/\Q$Type\E/$Replace/;
4656 $Repl->{$Base} = $Repl->{$Value};
4657 }
4658}
4659
4660sub macro_mangle($)
4661{
4662 my $Num = $_[0];
4663 if($Num==-1) {
4664 return "S_";
4665 }
4666 else
4667 {
4668 my $Code = "";
4669 if($Num<10)
4670 { # S0_, S1_, S2_, ...
4671 $Code = $Num;
4672 }
4673 elsif($Num>=10 and $Num<=35)
4674 { # SA_, SB_, SC_, ...
4675 $Code = chr(55+$Num);
4676 }
4677 else
4678 { # S10_, S11_, S12_
4679 $Code = $Num-26; # 26 is length of english alphabet
4680 }
4681 return "S".$Code."_";
4682 }
4683}
4684
4685sub write_stdcxx_substitution($)
4686{
4687 my $Mangled = $_[0];
4688 if($StdcxxMangling{$Mangled}) {
4689 return $StdcxxMangling{$Mangled};
4690 }
4691 else
4692 {
4693 my @Repls = keys(%StdcxxMangling);
4694 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4695 foreach my $MangledType (@Repls)
4696 {
4697 my $Replace = $StdcxxMangling{$MangledType};
4698 #if($Mangled!~/$Replace/) {
4699 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4700 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4701 #}
4702 }
4703 }
4704 return $Mangled;
4705}
4706
4707sub write_substitution($$)
4708{
4709 my ($Mangled, $Repl) = @_;
4710 if(defined $Repl->{$Mangled}
4711 and my $MnglNum = $Repl->{$Mangled}) {
4712 $Mangled = macro_mangle($MnglNum);
4713 }
4714 else
4715 {
4716 my @Repls = keys(%{$Repl});
4717 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4718 # FIXME: how to apply replacements? by num or by pos
4719 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4720 foreach my $MangledType (@Repls)
4721 {
4722 my $Replace = macro_mangle($Repl->{$MangledType});
4723 if($Mangled!~/$Replace/) {
4724 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4725 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4726 }
4727 }
4728 }
4729 return $Mangled;
4730}
4731
4732sub delete_keywords($)
4733{
4734 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004735 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004736 return $TypeName;
4737}
4738
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004739sub uncover_typedefs($$)
4740{
4741 my ($TypeName, $LibVersion) = @_;
4742 return "" if(not $TypeName);
4743 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4744 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4745 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004746 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004747 while($TypeName_New ne $TypeName_Pre)
4748 {
4749 $TypeName_Pre = $TypeName_New;
4750 my $TypeName_Copy = $TypeName_New;
4751 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004752 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004753 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004754 if(not $Intrinsic_Keywords{$1}) {
4755 $Words{$1} = 1;
4756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004757 }
4758 foreach my $Word (keys(%Words))
4759 {
4760 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4761 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004762 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004763 if($BaseType_Name=~/\([\*]+\)/)
4764 { # FuncPtr
4765 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4766 {
4767 my $Type_Suffix = $1;
4768 $TypeName_New = $BaseType_Name;
4769 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004770 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004771 }
4772 }
4773 }
4774 else
4775 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004776 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004777 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004778 }
4779 }
4780 }
4781 }
4782 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4783}
4784
4785sub isInternal($)
4786{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004787 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4788 {
4789 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4790 {
4791 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4792 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4793 return 1;
4794 }
4795 }
4796 }
4797 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004798}
4799
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004800sub getDataVal($$)
4801{
4802 my ($InfoId, $TypeId) = @_;
4803 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4804 {
4805 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4806 {
4807 if(defined $LibInfo{$Version}{"info_type"}{$1}
4808 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004809 {
4810 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004811 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004812 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4813 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004814 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004815 if(my $Addr = getTreeAttr_Op($1)) {
4816 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004817 }
4818 }
4819 }
4820 }
4821 else {
4822 return getInitVal($1, $TypeId);
4823 }
4824 }
4825 }
4826 return undef;
4827}
4828
4829sub getInitVal($$)
4830{
4831 my ($InfoId, $TypeId) = @_;
4832 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4833 {
4834 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4835 {
4836 if($InfoType eq "integer_cst")
4837 {
4838 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004839 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004840 { # characters
4841 $Val = chr($Val);
4842 }
4843 return $Val;
4844 }
4845 elsif($InfoType eq "string_cst") {
4846 return getNodeStrCst($InfoId);
4847 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004848 elsif($InfoType eq "var_decl")
4849 {
4850 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4851 return $Name;
4852 }
4853 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004854 }
4855 }
4856 return undef;
4857}
4858
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004859sub set_Class_And_Namespace($)
4860{
4861 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004862 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004863 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004864 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004865 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004866 my $NSInfoId = $1;
4867 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4868 {
4869 if($InfoType eq "namespace_decl") {
4870 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4871 }
4872 elsif($InfoType eq "record_type") {
4873 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4874 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004876 }
4877 }
4878 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4879 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004880 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004881 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004882 { # skip
4883 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004884 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004885 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004886
4887 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004888}
4889
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004890sub debugMangling($)
4891{
4892 my $LibVersion = $_[0];
4893 my %Mangled = ();
4894 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4895 {
4896 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4897 {
4898 if($Mngl=~/\A(_Z|\?)/) {
4899 $Mangled{$Mngl}=$InfoId;
4900 }
4901 }
4902 }
4903 translateSymbols(keys(%Mangled), $LibVersion);
4904 foreach my $Mngl (keys(%Mangled))
4905 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004906 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4907 my $U2 = $tr_name{$Mngl};
4908 if($U1 ne $U2) {
4909 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004910 }
4911 }
4912}
4913
4914sub linkSymbol($)
4915{ # link symbols from shared libraries
4916 # with the symbols from header files
4917 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004918 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004919 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004920 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4921 or $EMERGENCY_MODE_48)
4922 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4923 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4924 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004925 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004926 {
4927 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4928 return correct_incharge($InfoId, $Version, $Mangled);
4929 }
4930 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004931 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004932 or not $BinaryOnly
4933 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004934 { # 1. --headers-only mode
4935 # 2. not mangled src-only symbols
4936 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4937 return $Mangled;
4938 }
4939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004940 }
4941 return "";
4942}
4943
4944sub setLanguage($$)
4945{
4946 my ($LibVersion, $Lang) = @_;
4947 if(not $UserLang) {
4948 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4949 }
4950}
4951
4952sub getSymbolInfo($)
4953{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004954 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004955 if(isInternal($InfoId)) {
4956 return;
4957 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004958 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4959 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004960 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4961 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004962 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004963 return;
4964 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004965 setFuncAccess($InfoId);
4966 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004967 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4968 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004969 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004970 return;
4971 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004972
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004973 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004974 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004975 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004976 if(not defined $TypeInfo{$Version}{$Return}
4977 or not $TypeInfo{$Version}{$Return}{"Name"})
4978 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004979 delete($SymbolInfo{$Version}{$InfoId});
4980 return;
4981 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004982 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004983 }
4984 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4985 {
4986 if(defined $MissedTypedef{$Version}{$Rid})
4987 {
4988 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4989 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4990 }
4991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004992 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004993 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4994 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004995 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004996 my $Orig = getFuncOrig($InfoId);
4997 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004998 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4999 {
5000 delete($SymbolInfo{$Version}{$InfoId});
5001 return;
5002 }
5003
5004 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005005 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005006 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 return;
5008 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005009
5010 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005011 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005012 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5013
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005014 my @TParams = getTParams($Orig, "Func");
5015 if(not @TParams)
5016 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005017 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005018 return;
5019 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005020 foreach my $Pos (0 .. $#TParams)
5021 {
5022 my $Val = $TParams[$Pos];
5023 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5024
5025 if($Tmpl)
5026 {
5027 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5028 {
5029 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5030 }
5031 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005032 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005033
5034 if($Tmpl)
5035 {
5036 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5037 {
5038 if($Pos>$#TParams)
5039 {
5040 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5041 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5042 }
5043 }
5044 }
5045
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005046 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5047 { # operator<< <T>, operator>> <T>
5048 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5049 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005050 if(@TParams) {
5051 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5052 }
5053 else {
5054 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5055 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005056 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005057 }
5058 else
5059 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005060 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005061 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005062 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5063 {
5064 if($OSgroup eq "windows")
5065 { # cut the offset
5066 $MnglName=~s/\@\d+\Z//g;
5067 }
5068 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5069
5070 # NOTE: mangling of some symbols may change depending on GCC version
5071 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5072 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5073 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005074
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005075 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005076 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005077 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005078 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005079 return;
5080 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005081 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005082 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005083 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005084 if($Skip)
5085 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005086 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005087 return;
5088 }
5089 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005090 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5091 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5092 }
5093
5094 if(set_Class_And_Namespace($InfoId))
5095 {
5096 delete($SymbolInfo{$Version}{$InfoId});
5097 return;
5098 }
5099
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005100 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5101 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005102 if(not defined $TypeInfo{$Version}{$ClassId}
5103 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5104 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005105 delete($SymbolInfo{$Version}{$InfoId});
5106 return;
5107 }
5108 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005109 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5110 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005111 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005112 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005113 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005114 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005115 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005116 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 }
5118 if($COMMON_LANGUAGE{$Version} eq "C++")
5119 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005120 # C++ or --headers-only mode
5121 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005122 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005123 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5124 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005125 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005126 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005127 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005128 if(my $Mangled = linkSymbol($InfoId)) {
5129 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005130 }
5131 }
5132 if($OStarget eq "windows")
5133 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005134 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005135 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005136 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005137 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005138 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005140 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005141 }
5142 }
5143 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005144 else
5145 { # not mangled in C
5146 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5147 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005148 if(not $CheckHeadersOnly
5149 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5150 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5151 {
5152 my $Incorrect = 0;
5153
5154 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5155 {
5156 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5157 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5158 { # mangled in the TU dump, but not mangled in the library
5159 $Incorrect = 1;
5160 }
5161 }
5162 else
5163 {
5164 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5165 { # all C++ functions are not mangled in the TU dump
5166 $Incorrect = 1;
5167 }
5168 }
5169 if($Incorrect)
5170 {
5171 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5172 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5173 }
5174 }
5175 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005176 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005177 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005178 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005179 return;
5180 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005181 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005182 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005183 { # identify virtual and pure virtual functions
5184 # NOTE: constructors cannot be virtual
5185 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5186 # in the TU dump, so taking it from the original symbol
5187 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5188 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5189 { # NOTE: D2 destructors are not present in a v-table
5190 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005193 if(isInline($InfoId)) {
5194 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005195 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005196 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005197 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5198 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005199 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5200 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005201 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005202 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005203 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005205 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005206 }
5207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005208 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5209 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005210 if(not $ExtraDump)
5211 {
5212 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5213 { # non-target symbols
5214 delete($SymbolInfo{$Version}{$InfoId});
5215 return;
5216 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005218 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005219 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5220 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5221 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5222 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005223 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005224 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5225 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005226 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005227 return;
5228 }
5229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005230 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005231 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005232 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005234 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005235 return;
5236 }
5237 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005238 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 }
5240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005241 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5242 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5243 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5246 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005247 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005251 }
5252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005253 if(getFuncLink($InfoId) eq "Static") {
5254 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005256 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5257 {
5258 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5259 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005260 if($Unmangled=~/\.\_\d/)
5261 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005262 delete($SymbolInfo{$Version}{$InfoId});
5263 return;
5264 }
5265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005267
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005268 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5269 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005271 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5272 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005274
5275 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5276 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5277 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005278
5279 if($ExtraDump) {
5280 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5281 }
5282}
5283
5284sub guessHeader($)
5285{
5286 my $InfoId = $_[0];
5287 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5288 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5289 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5290 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5291 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5292 {
5293 if(get_filename($HPath) eq $Header)
5294 {
5295 my $HDir = get_filename(get_dirname($HPath));
5296 if($HDir ne "include"
5297 and $HDir=~/\A[a-z]+\Z/i) {
5298 return join_P($HDir, $Header);
5299 }
5300 }
5301 }
5302 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005303}
5304
5305sub isInline($)
5306{ # "body: undefined" in the tree
5307 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005308 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5309 {
5310 if($Info=~/ undefined /i) {
5311 return 0;
5312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005313 }
5314 return 1;
5315}
5316
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005317sub hasThrow($)
5318{
5319 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5320 {
5321 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5322 return getTreeAttr_Unql($1, "unql");
5323 }
5324 }
5325 return 1;
5326}
5327
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005328sub getTypeId($)
5329{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005330 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5331 {
5332 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5333 return $1;
5334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005335 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005336 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005337}
5338
5339sub setTypeMemb($$)
5340{
5341 my ($TypeId, $TypeAttr) = @_;
5342 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005343 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005344 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345 if($TypeType eq "Enum")
5346 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005347 my $MInfoId = getTreeAttr_Csts($TypeId);
5348 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005349 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005350 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5351 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005352 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005353 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5354 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005355 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005356 }
5357 }
5358 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5359 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005360 my $MInfoId = getTreeAttr_Flds($TypeId);
5361 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005363 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5364 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005365 if(not $IType or $IType ne "field_decl")
5366 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005367
5368 if($IType eq "var_decl")
5369 { # static field
5370 $StaticFields = 1;
5371 }
5372
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005373 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005374 next;
5375 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005376 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005377 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005378 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005379 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 }
5381 if(not $StructMembName)
5382 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005383 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005384 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005385 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005386 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5387 if(isAnon($UnnamedTName))
5388 { # rename unnamed fields to unnamed0, unnamed1, ...
5389 $StructMembName = "unnamed".($UnnamedPos++);
5390 }
5391 }
5392 }
5393 if(not $StructMembName)
5394 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005395 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005396 next;
5397 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005398 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005399 if(defined $MissedTypedef{$Version}{$MembTypeId})
5400 {
5401 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5402 $MembTypeId = $AddedTid;
5403 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005405
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005406 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5407 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005408 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005409 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005410 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5411 }
5412 if($MInfo=~/spec:\s*mutable /)
5413 { # mutable fields
5414 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005415 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005416 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005417 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5418 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005419 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005420 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005421 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005422 }
5423 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005424 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005425 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5426 { # template
5427 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5428 }
5429 else {
5430 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005433
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005434 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005435 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005436 }
5437 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005438
5439 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005440}
5441
5442sub setFuncParams($)
5443{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005444 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005445 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005446
5447 my $FType = getFuncType($InfoId);
5448
5449 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005450 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005451 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5452 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005454 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005455 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5456 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005457 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005458 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005460 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005461 else
5462 { # skip
5463 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005464 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005465 # skip "this"-parameter
5466 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005468 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005469 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005470 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005471 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5472 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5473 if(not $ParamName)
5474 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005475 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005476 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005477 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5478 {
5479 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5480 $ParamTypeId = $AddedTid;
5481 }
5482 }
5483 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005484 if(not $PType or $PType eq "Unknown") {
5485 return 1;
5486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005487 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005488 if(not $PTName) {
5489 return 1;
5490 }
5491 if($PTName eq "void") {
5492 last;
5493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005495 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005496 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005497 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005498 $ParamInfoId = getNextElem($ParamInfoId);
5499 next;
5500 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005501 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005502
5503 if(my %Base = get_BaseType($ParamTypeId, $Version))
5504 {
5505 if(defined $Base{"Template"}) {
5506 return 1;
5507 }
5508 }
5509
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005510 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005511 if(my $Algn = getAlgn($ParamInfoId)) {
5512 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5513 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005514 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5515 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005516 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 }
5518 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005519 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005520 if($ParamName ne "this" or $FType ne "Method") {
5521 $PPos += 1;
5522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005524 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005525 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005526 }
5527 return 0;
5528}
5529
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005530sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005532 my ($InfoId, $Vtt_Pos) = @_;
5533 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005534 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005535 my $FType = getFuncType($InfoId);
5536
5537 if($FType eq "Method")
5538 {
5539 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005540 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005542 if(not $ParamListElemId)
5543 { # foo(...)
5544 return 1;
5545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005546 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005547 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005548 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005549 { # actual params: may differ from formal args
5550 # formal int*const
5551 # actual: int*
5552 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 {
5554 $Vtt_Pos=-1;
5555 $ParamListElemId = getNextElem($ParamListElemId);
5556 next;
5557 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005558 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5559 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005560 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005561 $HaveVoid = 1;
5562 last;
5563 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005564 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005566 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5567 {
5568 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5569 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5570 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005571 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005572 }
5573 }
5574 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5575 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005576 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005577 { # params
5578 if($OldId ne $ParamTypeId)
5579 {
5580 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5581 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5582
5583 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5584 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5585 }
5586 }
5587 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005588 }
5589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005590 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005591 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005592 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5593 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005594 if($PurpType eq "nop_expr")
5595 { # func ( const char* arg = (const char*)(void*)0 )
5596 $PurpId = getTreeAttr_Op($PurpId);
5597 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005598 my $Val = getInitVal($PurpId, $ParamTypeId);
5599 if(defined $Val) {
5600 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005602 }
5603 }
5604 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005605 if($Pos!=0 or $FType ne "Method") {
5606 $PPos += 1;
5607 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005608 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005610 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005611}
5612
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005613sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005614{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005615 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005617 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5618 return $1;
5619 }
5620 }
5621 return "";
5622}
5623
5624sub getTreeAttr_Chain($)
5625{
5626 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5627 {
5628 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5629 return $1;
5630 }
5631 }
5632 return "";
5633}
5634
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005635sub getTreeAttr_Unql($)
5636{
5637 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5638 {
5639 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5640 return $1;
5641 }
5642 }
5643 return "";
5644}
5645
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005646sub getTreeAttr_Scpe($)
5647{
5648 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5649 {
5650 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5651 return $1;
5652 }
5653 }
5654 return "";
5655}
5656
5657sub getTreeAttr_Type($)
5658{
5659 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5660 {
5661 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5662 return $1;
5663 }
5664 }
5665 return "";
5666}
5667
5668sub getTreeAttr_Name($)
5669{
5670 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5671 {
5672 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5673 return $1;
5674 }
5675 }
5676 return "";
5677}
5678
5679sub getTreeAttr_Mngl($)
5680{
5681 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5682 {
5683 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5684 return $1;
5685 }
5686 }
5687 return "";
5688}
5689
5690sub getTreeAttr_Prms($)
5691{
5692 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5693 {
5694 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5695 return $1;
5696 }
5697 }
5698 return "";
5699}
5700
5701sub getTreeAttr_Fncs($)
5702{
5703 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5704 {
5705 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5706 return $1;
5707 }
5708 }
5709 return "";
5710}
5711
5712sub getTreeAttr_Csts($)
5713{
5714 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5715 {
5716 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5717 return $1;
5718 }
5719 }
5720 return "";
5721}
5722
5723sub getTreeAttr_Purp($)
5724{
5725 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5726 {
5727 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5728 return $1;
5729 }
5730 }
5731 return "";
5732}
5733
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005734sub getTreeAttr_Op($)
5735{
5736 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5737 {
5738 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5739 return $1;
5740 }
5741 }
5742 return "";
5743}
5744
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005745sub getTreeAttr_Valu($)
5746{
5747 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5748 {
5749 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5750 return $1;
5751 }
5752 }
5753 return "";
5754}
5755
5756sub getTreeAttr_Flds($)
5757{
5758 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5759 {
5760 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5761 return $1;
5762 }
5763 }
5764 return "";
5765}
5766
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005767sub getTreeAttr_Binf($)
5768{
5769 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5770 {
5771 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5772 return $1;
5773 }
5774 }
5775 return "";
5776}
5777
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005778sub getTreeAttr_Args($)
5779{
5780 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5781 {
5782 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005783 return $1;
5784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005785 }
5786 return "";
5787}
5788
5789sub getTreeValue($)
5790{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005791 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5792 {
5793 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5794 return $1;
5795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005796 }
5797 return "";
5798}
5799
5800sub getTreeAccess($)
5801{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005802 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005803 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005804 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5805 {
5806 my $Access = $1;
5807 if($Access eq "prot") {
5808 return "protected";
5809 }
5810 elsif($Access eq "priv") {
5811 return "private";
5812 }
5813 }
5814 elsif($Info=~/ protected /)
5815 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005816 return "protected";
5817 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005818 elsif($Info=~/ private /)
5819 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005820 return "private";
5821 }
5822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005823 return "public";
5824}
5825
5826sub setFuncAccess($)
5827{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005828 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005829 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005830 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005831 }
5832 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005833 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005834 }
5835}
5836
5837sub setTypeAccess($$)
5838{
5839 my ($TypeId, $TypeAttr) = @_;
5840 my $Access = getTreeAccess($TypeId);
5841 if($Access eq "protected") {
5842 $TypeAttr->{"Protected"} = 1;
5843 }
5844 elsif($Access eq "private") {
5845 $TypeAttr->{"Private"} = 1;
5846 }
5847}
5848
5849sub setFuncKind($)
5850{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005851 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5852 {
5853 if($Info=~/pseudo tmpl/) {
5854 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5855 }
5856 elsif($Info=~/ constructor /) {
5857 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5858 }
5859 elsif($Info=~/ destructor /) {
5860 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005862 }
5863}
5864
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005865sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005866{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005867 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5868 {
5869 if($Info=~/spec[ ]*:[ ]*pure /) {
5870 return "PureVirt";
5871 }
5872 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5873 return "Virt";
5874 }
5875 elsif($Info=~/ pure\s+virtual /)
5876 { # support for old GCC versions
5877 return "PureVirt";
5878 }
5879 elsif($Info=~/ virtual /)
5880 { # support for old GCC versions
5881 return "Virt";
5882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883 }
5884 return "";
5885}
5886
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887sub getFuncLink($)
5888{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005889 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5890 {
5891 if($Info=~/link[ ]*:[ ]*static /) {
5892 return "Static";
5893 }
5894 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005895 return $1;
5896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005897 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005898 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005899}
5900
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005901sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005902{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005903 my ($Symbol, $LibVersion) = @_;
5904 return "" if(not $Symbol or not $LibVersion);
5905 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5906 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005907 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005908 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5909 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5910 }
5911 }
5912 if($NS)
5913 {
5914 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5915 return $NS;
5916 }
5917 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005918 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005919 while($NS=~s/::[^:]+\Z//)
5920 {
5921 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5922 return $NS;
5923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924 }
5925 }
5926 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005927
5928 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929}
5930
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005931sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005932{
5933 my ($TypeName, $LibVersion) = @_;
5934 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005935 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5938 return $NS;
5939 }
5940 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005941 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005942 while($NS=~s/::[^:]+\Z//)
5943 {
5944 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5945 return $NS;
5946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005947 }
5948 }
5949 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005950 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005951}
5952
5953sub getNameSpace($)
5954{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005955 my $InfoId = $_[0];
5956 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005958 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005960 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005961 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005962 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5963 {
5964 my $NameSpace = getTreeStr($1);
5965 if($NameSpace eq "::")
5966 { # global namespace
5967 return "";
5968 }
5969 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5970 $NameSpace = $BaseNameSpace."::".$NameSpace;
5971 }
5972 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5973 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005974 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005975 else {
5976 return "";
5977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005979 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005980 { # inside data type
5981 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5982 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005985 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005986 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987}
5988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005989sub getEnumMembVal($)
5990{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005991 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005992 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005993 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5994 {
5995 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5996 {
5997 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5998 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5999 return getTreeValue($1);
6000 }
6001 else
6002 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6003 return getTreeValue($1);
6004 }
6005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006006 }
6007 }
6008 return "";
6009}
6010
6011sub getSize($)
6012{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006013 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6014 {
6015 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6016 return getTreeValue($1);
6017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006018 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006019 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020}
6021
6022sub getAlgn($)
6023{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006024 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6025 {
6026 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6027 return $1;
6028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006031}
6032
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006033sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006034{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006035 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6036 {
6037 if($Info=~/ bitfield /) {
6038 return getSize($_[0]);
6039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006040 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006042}
6043
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006044sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006045{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006046 if(my $Chan = getTreeAttr_Chan($_[0])) {
6047 return $Chan;
6048 }
6049 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6050 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006052 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006053}
6054
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006055sub registerHeader($$)
6056{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006058 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059 return "";
6060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006061 if(is_abs($Header) and not -f $Header)
6062 { # incorrect absolute path
6063 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006065 if(skipHeader($Header, $LibVersion))
6066 { # skip
6067 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006069 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6070 {
6071 detect_header_includes($Header_Path, $LibVersion);
6072
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006073 if(defined $Tolerance and $Tolerance=~/3/)
6074 { # 3 - skip headers that include non-Linux headers
6075 if($OSgroup ne "windows")
6076 {
6077 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6078 {
6079 if(specificHeader($Inc, "windows")) {
6080 return "";
6081 }
6082 }
6083 }
6084 }
6085
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006086 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6087 { # redirect
6088 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6089 or skipHeader($RHeader_Path, $LibVersion))
6090 { # skip
6091 return "";
6092 }
6093 $Header_Path = $RHeader_Path;
6094 }
6095 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6096 { # skip
6097 return "";
6098 }
6099
6100 if(my $HName = get_filename($Header_Path))
6101 { # register
6102 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6103 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6104 }
6105
6106 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6107 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006108 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006109 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006110 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006111 }
6112
6113 if($CheckHeadersOnly
6114 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6115 { # /usr/include/c++/4.6.1/...
6116 $STDCXX_TESTING = 1;
6117 }
6118
6119 return $Header_Path;
6120 }
6121 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006122}
6123
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006124sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006125{
6126 my ($Dir, $WithDeps, $LibVersion) = @_;
6127 $Dir=~s/[\/\\]+\Z//g;
6128 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006129 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006130
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006132 if($WithDeps)
6133 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006134 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6135 return;
6136 }
6137 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6138 $Mode = "DepsOnly";
6139 }
6140 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006141 else
6142 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006143 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6144 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6145 return;
6146 }
6147 }
6148 $Header_Dependency{$LibVersion}{$Dir} = 1;
6149 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6150 if($Mode eq "DepsOnly")
6151 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006152 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153 $Header_Dependency{$LibVersion}{$Path} = 1;
6154 }
6155 return;
6156 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006157 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006158 {
6159 if($WithDeps)
6160 {
6161 my $SubDir = $Path;
6162 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6163 { # register all sub directories
6164 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6165 }
6166 }
6167 next if(is_not_header($Path));
6168 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006169 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006170 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006171 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6172 }
6173 }
6174 if(get_filename($Dir) eq "include")
6175 { # search for "lib/include/" directory
6176 my $LibDir = $Dir;
6177 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006178 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179 }
6180 }
6181}
6182
6183sub parse_redirect($$$)
6184{
6185 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006186 my @Errors = ();
6187 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6188 push(@Errors, $1);
6189 }
6190 my $Redirect = "";
6191 foreach (@Errors)
6192 {
6193 s/\s{2,}/ /g;
6194 if(/(only|must\ include
6195 |update\ to\ include
6196 |replaced\ with
6197 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006198 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006199 {
6200 $Redirect = $2;
6201 last;
6202 }
6203 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6204 {
6205 $Redirect = $2;
6206 last;
6207 }
6208 elsif(/this\ header\ should\ not\ be\ used
6209 |programs\ should\ not\ directly\ include
6210 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6211 |is\ not\ supported\ API\ for\ general\ use
6212 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006213 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006214 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6215 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6216 }
6217 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006218 if($Redirect)
6219 {
6220 $Redirect=~s/\A<//g;
6221 $Redirect=~s/>\Z//g;
6222 }
6223 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006224}
6225
6226sub parse_includes($$)
6227{
6228 my ($Content, $Path) = @_;
6229 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006230 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006231 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006232 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006233 my $Method = substr($Header, 0, 1, "");
6234 substr($Header, length($Header)-1, 1, "");
6235 $Header = path_format($Header, $OSgroup);
6236 if($Method eq "\"" or is_abs($Header))
6237 {
6238 if(-e join_P(get_dirname($Path), $Header))
6239 { # relative path exists
6240 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006241 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006242 else
6243 { # include "..." that doesn't exist is equal to include <...>
6244 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006246 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006247 else {
6248 $Includes{$Header} = 1;
6249 }
6250 }
6251 if($ExtraInfo)
6252 {
6253 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6254 { # FT_FREETYPE_H
6255 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 }
6257 }
6258 return \%Includes;
6259}
6260
6261sub ignore_path($)
6262{
6263 my $Path = $_[0];
6264 if($Path=~/\~\Z/)
6265 {# skipping system backup files
6266 return 1;
6267 }
6268 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6269 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6270 return 1;
6271 }
6272 return 0;
6273}
6274
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006275sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006276{
6277 my ($ArrRef, $W) = @_;
6278 return if(length($W)<2);
6279 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6280}
6281
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006282sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006283{
6284 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006285
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006286 $H1=~s/\.[a-z]+\Z//ig;
6287 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006288
6289 my $Hname1 = get_filename($H1);
6290 my $Hname2 = get_filename($H2);
6291 my $HDir1 = get_dirname($H1);
6292 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006293 my $Dirname1 = get_filename($HDir1);
6294 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006295
6296 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6297 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6298
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006299 if($_[0] eq $_[1]
6300 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006301 return 0;
6302 }
6303 elsif($H1=~/\A\Q$H2\E/) {
6304 return 1;
6305 }
6306 elsif($H2=~/\A\Q$H1\E/) {
6307 return -1;
6308 }
6309 elsif($HDir1=~/\Q$Hname1\E/i
6310 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006311 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006312 return -1;
6313 }
6314 elsif($HDir2=~/\Q$Hname2\E/i
6315 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006316 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006317 return 1;
6318 }
6319 elsif($Hname1=~/\Q$Dirname1\E/i
6320 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006321 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 return -1;
6323 }
6324 elsif($Hname2=~/\Q$Dirname2\E/i
6325 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006326 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006327 return 1;
6328 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006329 elsif($Hname1=~/(config|lib|util)/i
6330 and $Hname2!~/(config|lib|util)/i)
6331 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006332 return -1;
6333 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006334 elsif($Hname2=~/(config|lib|util)/i
6335 and $Hname1!~/(config|lib|util)/i)
6336 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006337 return 1;
6338 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006339 else
6340 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006341 my $R1 = checkRelevance($H1);
6342 my $R2 = checkRelevance($H2);
6343 if($R1 and not $R2)
6344 { # libebook/e-book.h
6345 return -1;
6346 }
6347 elsif($R2 and not $R1)
6348 { # libebook/e-book.h
6349 return 1;
6350 }
6351 else
6352 {
6353 return (lc($H1) cmp lc($H2));
6354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006355 }
6356}
6357
6358sub searchForHeaders($)
6359{
6360 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006362 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006363 registerGccHeaders();
6364
6365 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6366 { # c++ standard include paths
6367 registerCppHeaders();
6368 }
6369
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006370 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006371 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6372 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006373 {
6374 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006375 if($SystemRoot)
6376 {
6377 if(is_abs($Path)) {
6378 $Path = $SystemRoot.$Path;
6379 }
6380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 if(not -e $Path) {
6382 exitStatus("Access_Error", "can't access \'$Path\'");
6383 }
6384 elsif(-f $Path) {
6385 exitStatus("Access_Error", "\'$Path\' - not a directory");
6386 }
6387 elsif(-d $Path)
6388 {
6389 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006390 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006391 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6392 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006393 }
6394 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006395 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006396 }
6397 }
6398 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006399 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006400 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6401 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006402
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006403 # registering directories
6404 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6405 {
6406 next if(not -e $Path);
6407 $Path = get_abs_path($Path);
6408 $Path = path_format($Path, $OSgroup);
6409 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006410 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 }
6412 elsif(-f $Path)
6413 {
6414 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006415 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006416 and not $LocalIncludes{$Dir})
6417 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006418 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006419 # if(my $OutDir = get_dirname($Dir))
6420 # { # registering the outer directory
6421 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6422 # and not $LocalIncludes{$OutDir}) {
6423 # registerDir($OutDir, 0, $LibVersion);
6424 # }
6425 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006426 }
6427 }
6428 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006429
6430 # clean memory
6431 %RegisteredDirs = ();
6432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 # registering headers
6434 my $Position = 0;
6435 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6436 {
6437 if(is_abs($Dest) and not -e $Dest) {
6438 exitStatus("Access_Error", "can't access \'$Dest\'");
6439 }
6440 $Dest = path_format($Dest, $OSgroup);
6441 if(is_header($Dest, 1, $LibVersion))
6442 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006443 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006444 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6445 }
6446 }
6447 elsif(-d $Dest)
6448 {
6449 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006450 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006451 {
6452 next if(ignore_path($Path));
6453 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006454 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006455 push(@Registered, $HPath);
6456 }
6457 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006458 @Registered = sort {sortHeaders($a, $b)} @Registered;
6459 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 foreach my $Path (@Registered) {
6461 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6462 }
6463 }
6464 else {
6465 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6466 }
6467 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006468
6469 if(defined $Tolerance and $Tolerance=~/4/)
6470 { # 4 - skip headers included by others
6471 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6472 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006473 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006474 delete($Registered_Headers{$LibVersion}{$Path});
6475 }
6476 }
6477 }
6478
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006479 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6480 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006481 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006482 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006483 if(is_abs($Header) and not -f $Header) {
6484 exitStatus("Access_Error", "can't access file \'$Header\'");
6485 }
6486 $Header = path_format($Header, $OSgroup);
6487 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6488 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006489 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006490 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006491 }
6492 else {
6493 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006495 }
6496 }
6497 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6498 { # set relative paths (for duplicates)
6499 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6500 { # search for duplicates
6501 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6502 my $Prefix = get_dirname($FirstPath);
6503 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6504 { # detect a shortest distinguishing prefix
6505 my $NewPrefix = $1;
6506 my %Identity = ();
6507 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6508 {
6509 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6510 $Identity{$Path} = $1;
6511 }
6512 }
6513 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006514 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006515 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6516 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6517 }
6518 last;
6519 }
6520 $Prefix = $NewPrefix; # increase prefix
6521 }
6522 }
6523 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006524
6525 # clean memory
6526 %HeaderName_Paths = ();
6527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006528 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6529 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006530 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006531 my ($Pos, $PairPos) = (-1, -1);
6532 my ($Path, $PairPath) = ();
6533 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6534 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6535 foreach my $Header_Path (@Paths)
6536 {
6537 if(get_filename($Header_Path) eq $PairName)
6538 {
6539 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6540 $PairPath = $Header_Path;
6541 }
6542 if(get_filename($Header_Path) eq $HeaderName)
6543 {
6544 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6545 $Path = $Header_Path;
6546 }
6547 }
6548 if($PairPos!=-1 and $Pos!=-1
6549 and int($PairPos)<int($Pos))
6550 {
6551 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6552 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6553 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6554 }
6555 }
6556 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6557 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6558 }
6559}
6560
6561sub detect_real_includes($$)
6562{
6563 my ($AbsPath, $LibVersion) = @_;
6564 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6565 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6566 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6567 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6568 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006569 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6570
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006571 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6572 return () if(not $Path);
6573 open(PREPROC, $Path);
6574 while(<PREPROC>)
6575 {
6576 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6577 {
6578 my $Include = path_format($1, $OSgroup);
6579 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6580 next;
6581 }
6582 if($Include eq $AbsPath) {
6583 next;
6584 }
6585 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6586 }
6587 }
6588 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006589 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6590}
6591
6592sub detect_header_includes($$)
6593{
6594 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006595 return if(not $LibVersion or not $Path);
6596 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6597 return;
6598 }
6599 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6600
6601 if(not -e $Path) {
6602 return;
6603 }
6604
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006605 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006606 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6607 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006608 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006609 {
6610 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006611 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006612 }
6613 if($RedirectPath ne $Path) {
6614 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6615 }
6616 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006617 else
6618 { # can't find
6619 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006622 if(my $Inc = parse_includes($Content, $Path))
6623 {
6624 foreach my $Include (keys(%{$Inc}))
6625 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006626 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006627
6628 if(defined $Tolerance and $Tolerance=~/4/)
6629 {
6630 if(my $HPath = identifyHeader($Include, $LibVersion))
6631 {
6632 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6633 }
6634 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006637}
6638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006639sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006640{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006641 my $Path = $_[0];
6642 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006643 if($OStarget eq "symbian")
6644 {
6645 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6646 { # epoc32/include/libc/{stdio, ...}.h
6647 return 1;
6648 }
6649 }
6650 else
6651 {
6652 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6653 { # /usr/include/{stdio, ...}.h
6654 return 1;
6655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006657 return 0;
6658}
6659
6660sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006661{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 my $Dir = $_[0];
6663 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006664 if($OStarget eq "symbian")
6665 {
6666 if(get_filename($OutDir) eq "libc"
6667 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6668 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6669 return 1;
6670 }
6671 }
6672 else
6673 { # linux
6674 if($OutDir eq "/usr/include"
6675 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6676 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6677 return 1;
6678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006679 }
6680 return 0;
6681}
6682
6683sub detect_recursive_includes($$)
6684{
6685 my ($AbsPath, $LibVersion) = @_;
6686 return () if(not $AbsPath);
6687 if(isCyclical(\@RecurInclude, $AbsPath)) {
6688 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6689 }
6690 my ($AbsDir, $Name) = separate_path($AbsPath);
6691 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006692 { # system GLIBC internals
6693 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006694 }
6695 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6696 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6697 }
6698 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006699
6700 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6701 { # skip /usr/include/c++/*/ headers
6702 return () if(not $ExtraInfo);
6703 }
6704
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006705 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006706 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006707 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006708 { # check "real" (non-"model") include paths
6709 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6710 pop(@RecurInclude);
6711 return @Paths;
6712 }
6713 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6714 detect_header_includes($AbsPath, $LibVersion);
6715 }
6716 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6717 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006718 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006719 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006720 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006721 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006722 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006724 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 }
6726 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006727 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006728 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 { # search for the nearest header
6730 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006731 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006732 if(-f $Candidate) {
6733 $HPath = $Candidate;
6734 }
6735 }
6736 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006737 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006738 }
6739 next if(not $HPath);
6740 if($HPath eq $AbsPath) {
6741 next;
6742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006743
6744 if($Debug)
6745 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006746# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6747# {
6748# print STDERR "$AbsPath -> $HPath\n";
6749# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006750 }
6751
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006752 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6753 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006754 { # only include <...>, skip include "..." prefixes
6755 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6756 }
6757 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6758 {
6759 if($IncPath eq $AbsPath) {
6760 next;
6761 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006762 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6763 if($RIncType==-1)
6764 { # include "..."
6765 $RIncType = $IncType;
6766 }
6767 elsif($RIncType==2)
6768 {
6769 if($IncType!=-1) {
6770 $RIncType = $IncType;
6771 }
6772 }
6773 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006774 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6775 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6776 }
6777 }
6778 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6779 {
6780 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6781 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6782 { # distinguish math.h from glibc and math.h from the tested library
6783 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6784 last;
6785 }
6786 }
6787 }
6788 pop(@RecurInclude);
6789 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6790}
6791
6792sub find_in_framework($$$)
6793{
6794 my ($Header, $Framework, $LibVersion) = @_;
6795 return "" if(not $Header or not $Framework or not $LibVersion);
6796 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6797 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6798 }
6799 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6800 {
6801 if(get_filename($Dependency) eq $Framework
6802 and -f get_dirname($Dependency)."/".$Header) {
6803 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6804 }
6805 }
6806 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6807}
6808
6809sub find_in_defaults($)
6810{
6811 my $Header = $_[0];
6812 return "" if(not $Header);
6813 if(defined $Cache{"find_in_defaults"}{$Header}) {
6814 return $Cache{"find_in_defaults"}{$Header};
6815 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006816 foreach my $Dir (@DefaultIncPaths,
6817 @DefaultGccPaths,
6818 @DefaultCppPaths,
6819 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006820 {
6821 next if(not $Dir);
6822 if(-f $Dir."/".$Header) {
6823 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6824 }
6825 }
6826 return ($Cache{"find_in_defaults"}{$Header}="");
6827}
6828
6829sub cmp_paths($$)
6830{
6831 my ($Path1, $Path2) = @_;
6832 my @Parts1 = split(/[\/\\]/, $Path1);
6833 my @Parts2 = split(/[\/\\]/, $Path2);
6834 foreach my $Num (0 .. $#Parts1)
6835 {
6836 my $Part1 = $Parts1[$Num];
6837 my $Part2 = $Parts2[$Num];
6838 if($GlibcDir{$Part1}
6839 and not $GlibcDir{$Part2}) {
6840 return 1;
6841 }
6842 elsif($GlibcDir{$Part2}
6843 and not $GlibcDir{$Part1}) {
6844 return -1;
6845 }
6846 elsif($Part1=~/glib/
6847 and $Part2!~/glib/) {
6848 return 1;
6849 }
6850 elsif($Part1!~/glib/
6851 and $Part2=~/glib/) {
6852 return -1;
6853 }
6854 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6855 return $CmpRes;
6856 }
6857 }
6858 return 0;
6859}
6860
6861sub checkRelevance($)
6862{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006863 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006864 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006865
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006866 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006867 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006868 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006869
6870 my $Name = lc(get_filename($Path));
6871 my $Dir = lc(get_dirname($Path));
6872
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006873 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006874
6875 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006876 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006877 my $Len = length($Token);
6878 next if($Len<=1);
6879 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6880 { # include/evolution-data-server-1.4/libebook/e-book.h
6881 return 1;
6882 }
6883 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006884 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006885 return 1;
6886 }
6887 }
6888 return 0;
6889}
6890
6891sub checkFamily(@)
6892{
6893 my @Paths = @_;
6894 return 1 if($#Paths<=0);
6895 my %Prefix = ();
6896 foreach my $Path (@Paths)
6897 {
6898 if($SystemRoot) {
6899 $Path = cut_path_prefix($Path, $SystemRoot);
6900 }
6901 if(my $Dir = get_dirname($Path))
6902 {
6903 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6904 $Prefix{$Dir} += 1;
6905 $Prefix{get_dirname($Dir)} += 1;
6906 }
6907 }
6908 foreach (sort keys(%Prefix))
6909 {
6910 if(get_depth($_)>=3
6911 and $Prefix{$_}==$#Paths+1) {
6912 return 1;
6913 }
6914 }
6915 return 0;
6916}
6917
6918sub isAcceptable($$$)
6919{
6920 my ($Header, $Candidate, $LibVersion) = @_;
6921 my $HName = get_filename($Header);
6922 if(get_dirname($Header))
6923 { # with prefix
6924 return 1;
6925 }
6926 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6927 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6928 return 1;
6929 }
6930 if(checkRelevance($Candidate))
6931 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6932 return 1;
6933 }
6934 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6935 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6936 # /usr/include/qt4/Qt/qsslconfiguration.h
6937 return 1;
6938 }
6939 if($OStarget eq "symbian")
6940 {
6941 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6942 return 1;
6943 }
6944 }
6945 return 0;
6946}
6947
6948sub isRelevant($$$)
6949{ # disallow to search for "abstract" headers in too deep directories
6950 my ($Header, $Candidate, $LibVersion) = @_;
6951 my $HName = get_filename($Header);
6952 if($OStarget eq "symbian")
6953 {
6954 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6955 return 0;
6956 }
6957 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006958 if($OStarget ne "bsd")
6959 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006960 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6961 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6962 return 0;
6963 }
6964 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006965 if($OStarget ne "windows")
6966 {
6967 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6968 { # skip /usr/include/wine/msvcrt
6969 return 0;
6970 }
6971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006972 if(not get_dirname($Header)
6973 and $Candidate=~/[\/\\]wx[\/\\]/)
6974 { # do NOT search in system /wx/ directory
6975 # for headers without a prefix: sstream.h
6976 return 0;
6977 }
6978 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6979 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6980 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6981 return 0;
6982 }
6983 if($Candidate=~/[\/\\]asm-/
6984 and (my $Arch = getArch($LibVersion)) ne "unknown")
6985 { # arch-specific header files
6986 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6987 {# skip ../asm-arm/ if using x86 architecture
6988 return 0;
6989 }
6990 }
6991 my @Candidates = getSystemHeaders($HName, $LibVersion);
6992 if($#Candidates==1)
6993 { # unique header
6994 return 1;
6995 }
6996 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6997 if($#SCandidates==1)
6998 { # unique name
6999 return 1;
7000 }
7001 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7002 if(get_depth($Candidate)-$SystemDepth>=5)
7003 { # abstract headers in too deep directories
7004 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7005 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7006 return 0;
7007 }
7008 }
7009 if($Header eq "parser.h"
7010 and $Candidate!~/\/libxml2\//)
7011 { # select parser.h from xml2 library
7012 return 0;
7013 }
7014 if(not get_dirname($Header)
7015 and keys(%{$SystemHeaders{$HName}})>=3)
7016 { # many headers with the same name
7017 # like thread.h included without a prefix
7018 if(not checkFamily(@Candidates)) {
7019 return 0;
7020 }
7021 }
7022 return 1;
7023}
7024
7025sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007026{ # cache function
7027 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7028 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7029 }
7030 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7031}
7032
7033sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007034{
7035 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007036 if(-f $Header) {
7037 return $Header;
7038 }
7039 if(is_abs($Header) and not -f $Header)
7040 { # incorrect absolute path
7041 return "";
7042 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007043 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007044 { # too abstract configuration headers
7045 return "";
7046 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007047 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007048 if($OSgroup ne "windows")
7049 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007050 if(defined $WinHeaders{lc($HName)}
7051 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007052 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007053 return "";
7054 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007055 }
7056 if($OSgroup ne "macos")
7057 {
7058 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007059 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007060 return "";
7061 }
7062 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007063
7064 if(defined $ObsoleteHeaders{$HName})
7065 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007066 return "";
7067 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007068 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7069 {
7070 if(defined $AlienHeaders{$HName}
7071 or defined $AlienHeaders{$Header})
7072 { # alien headers from other systems
7073 return "";
7074 }
7075 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007076
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007077 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007078 { # search in default paths
7079 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007080 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007081 }
7082 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007083 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007084 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007085 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007086 }
7087 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7088 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7089 {
7090 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007091 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007092 }
7093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007094 # error
7095 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007096}
7097
7098sub getSystemHeaders($$)
7099{
7100 my ($Header, $LibVersion) = @_;
7101 my @Candidates = ();
7102 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7103 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007104 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007105 next;
7106 }
7107 push(@Candidates, $Candidate);
7108 }
7109 return @Candidates;
7110}
7111
7112sub cut_path_prefix($$)
7113{
7114 my ($Path, $Prefix) = @_;
7115 return $Path if(not $Prefix);
7116 $Prefix=~s/[\/\\]+\Z//;
7117 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7118 return $Path;
7119}
7120
7121sub is_default_include_dir($)
7122{
7123 my $Dir = $_[0];
7124 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007125 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007126}
7127
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007128sub identifyHeader($$)
7129{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007130 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007131 if(not $Header) {
7132 return "";
7133 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007134 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007135 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7136 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007138 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139}
7140
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007142{ # search for header by absolute path, relative path or name
7143 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007144 if(-f $Header)
7145 { # it's relative or absolute path
7146 return get_abs_path($Header);
7147 }
7148 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7149 and my $HeaderDir = find_in_defaults($Header))
7150 { # search for libc headers in the /usr/include
7151 # for non-libc target library before searching
7152 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007153 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007154 }
7155 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7156 { # search in the target library paths
7157 return $Path;
7158 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007159 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007160 { # search in the internal GCC include paths
7161 return $DefaultGccHeader{$Header};
7162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007163 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007165 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007166 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007167 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168 { # search in the default G++ include paths
7169 return $DefaultCppHeader{$Header};
7170 }
7171 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7172 { # search everywhere in the system
7173 return $AnyPath;
7174 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007175 elsif($OSgroup eq "macos")
7176 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7177 if(my $Dir = get_dirname($Header))
7178 {
7179 my $RelPath = "Headers\/".get_filename($Header);
7180 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007181 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007182 }
7183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007184 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007185 # cannot find anything
7186 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007187}
7188
7189sub getLocation($)
7190{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007191 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7192 {
7193 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007194 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007196 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007197 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007198}
7199
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007200sub getNameByInfo($)
7201{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007202 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007203 {
7204 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7205 {
7206 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7207 {
7208 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7209 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007210 my $Str = $1;
7211 if($CppMode{$Version}
7212 and $Str=~/\Ac99_(.+)\Z/)
7213 {
7214 if($CppKeywords_A{$1}) {
7215 $Str=$1;
7216 }
7217 }
7218 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007219 }
7220 }
7221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007222 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007223 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007224}
7225
7226sub getTreeStr($)
7227{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007228 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007230 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7231 {
7232 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007233 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007234 and $Str=~/\Ac99_(.+)\Z/)
7235 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007236 if($CppKeywords_A{$1}) {
7237 $Str=$1;
7238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007240 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007242 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007243 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244}
7245
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007246sub getFuncShortName($)
7247{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007248 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007249 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007250 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007251 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007252 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007253 {
7254 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7255 {
7256 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7257 return "operator ".$RName;
7258 }
7259 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007260 }
7261 else
7262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007263 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7264 {
7265 if(my $Ind = $Operator_Indication{$1}) {
7266 return "operator".$Ind;
7267 }
7268 elsif(not $UnknownOperator{$1})
7269 {
7270 printMsg("WARNING", "unknown operator $1");
7271 $UnknownOperator{$1} = 1;
7272 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007273 }
7274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007275 }
7276 else
7277 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007278 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7279 return getTreeStr($1);
7280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281 }
7282 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007283 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007284}
7285
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007286sub getFuncReturn($)
7287{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007288 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7289 {
7290 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7291 {
7292 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7293 return $1;
7294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007295 }
7296 }
7297 return "";
7298}
7299
7300sub getFuncOrig($)
7301{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007302 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7303 {
7304 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7305 return $1;
7306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007308 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309}
7310
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311sub unmangleArray(@)
7312{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007313 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007314 { # MSVC mangling
7315 my $UndNameCmd = get_CmdPath("undname");
7316 if(not $UndNameCmd) {
7317 exitStatus("Not_Found", "can't find \"undname\"");
7318 }
7319 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007320 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 }
7322 else
7323 { # GCC mangling
7324 my $CppFiltCmd = get_CmdPath("c++filt");
7325 if(not $CppFiltCmd) {
7326 exitStatus("Not_Found", "can't find c++filt in PATH");
7327 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007328 if(not defined $CPPFILT_SUPPORT_FILE)
7329 {
7330 my $Info = `$CppFiltCmd -h 2>&1`;
7331 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7332 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007333 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007334 if($CPPFILT_SUPPORT_FILE)
7335 { # new versions of c++filt can take a file
7336 if($#_>$MAX_CPPFILT_FILE_SIZE)
7337 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7338 # this is fixed in the oncoming version of Binutils
7339 my @Half = splice(@_, 0, ($#_+1)/2);
7340 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007342 else
7343 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007344 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7345 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7346 if($?==139)
7347 { # segmentation fault
7348 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7349 }
7350 return split(/\n/, $Res);
7351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007352 }
7353 else
7354 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007355 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7356 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007357 my @Half = splice(@_, 0, ($#_+1)/2);
7358 return (unmangleArray(@Half), unmangleArray(@_))
7359 }
7360 else
7361 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007363 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7364 if($?==139)
7365 { # segmentation fault
7366 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7367 }
7368 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007369 }
7370 }
7371 }
7372}
7373
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374sub get_ChargeLevel($$)
7375{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007376 my ($Symbol, $LibVersion) = @_;
7377 return "" if($Symbol!~/\A(_Z|\?)/);
7378 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7379 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007380 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007381 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007382 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007383 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007384 return "[in-charge]";
7385 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007386 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387 return "[not-in-charge]";
7388 }
7389 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007390 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007392 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007393 return "[in-charge]";
7394 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007395 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007396 return "[not-in-charge]";
7397 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007398 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 return "[in-charge-deleting]";
7400 }
7401 }
7402 }
7403 else
7404 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007405 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 return "[in-charge]";
7407 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007408 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 return "[not-in-charge]";
7410 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007411 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007412 return "[in-charge]";
7413 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007414 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 return "[not-in-charge]";
7416 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007417 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007418 return "[in-charge-deleting]";
7419 }
7420 }
7421 return "";
7422}
7423
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007424sub get_Signature_M($$)
7425{
7426 my ($Symbol, $LibVersion) = @_;
7427 my $Signature_M = $tr_name{$Symbol};
7428 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7429 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007430 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007431 }
7432 return $Signature_M;
7433}
7434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435sub get_Signature($$)
7436{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007437 my ($Symbol, $LibVersion) = @_;
7438 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7439 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007440 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007441 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007442 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007443
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007444 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7445 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007447 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7448 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007449 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7450 $ClassName=~s/\bstruct //g;
7451 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007452 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7453 $Signature .= "~";
7454 }
7455 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007456 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007457 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007458 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007459 }
7460 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007461 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007463 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7464 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007466 else
7467 {
7468 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007469 }
7470 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007471 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 {
7473 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007474 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007476 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007477 if(not $ParamTypeName) {
7478 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7479 }
7480 foreach my $Typedef (keys(%ChangedTypedef))
7481 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007482 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7483 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007486 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7487 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007488 if($ParamName eq "this"
7489 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007490 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007491 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007492 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007493 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 }
7495 else {
7496 push(@ParamArray, $ParamTypeName);
7497 }
7498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007499 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7500 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007501 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007502 }
7503 else
7504 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007507 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007509 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007510 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7511 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007512 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007513 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007514 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7515 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007516 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007517 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007518 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7519 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007520 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007521 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007522 }
7523 }
7524 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007525 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007526 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007527 }
7528 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007529 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007531 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007532}
7533
7534sub create_member_decl($$)
7535{
7536 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007537 if($TName=~/\([\*]+\)/)
7538 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7540 return $TName;
7541 }
7542 else
7543 {
7544 my @ArraySizes = ();
7545 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7546 push(@ArraySizes, $1);
7547 }
7548 return $TName." ".$Member.join("", @ArraySizes);
7549 }
7550}
7551
7552sub getFuncType($)
7553{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007554 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7555 {
7556 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7557 {
7558 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7559 {
7560 if($Type eq "method_type") {
7561 return "Method";
7562 }
7563 elsif($Type eq "function_type") {
7564 return "Function";
7565 }
7566 else {
7567 return "Other";
7568 }
7569 }
7570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007571 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007572 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007573}
7574
7575sub getFuncTypeId($)
7576{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007577 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7578 {
7579 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7580 return $1;
7581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007583 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007584}
7585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007586sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007587{ # "._N" or "$_N" in older GCC versions
7588 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007589}
7590
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007591sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007592{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007593 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7594 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007595 }
7596
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007597 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007598
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007599 if($_[1] ne "S")
7600 {
7601 $N=~s/\A[ ]+//g;
7602 $N=~s/[ ]+\Z//g;
7603 $N=~s/[ ]{2,}/ /g;
7604 }
7605
7606 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007607
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007608 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007609
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007610 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7611 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007612
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007613 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007614
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007615 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007617 if($_[1] eq "S")
7618 {
7619 if(index($N, "operator")!=-1) {
7620 $N=~s/\b(operator[ ]*)> >/$1>>/;
7621 }
7622 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007623
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007624 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007625}
7626
7627sub get_HeaderDeps($$)
7628{
7629 my ($AbsPath, $LibVersion) = @_;
7630 return () if(not $AbsPath or not $LibVersion);
7631 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7632 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7633 }
7634 my %IncDir = ();
7635 detect_recursive_includes($AbsPath, $LibVersion);
7636 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7637 {
7638 next if(not $HeaderPath);
7639 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7640 my $Dir = get_dirname($HeaderPath);
7641 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7642 {
7643 my $Dep = $Dir;
7644 if($Prefix)
7645 {
7646 if($OSgroup eq "windows")
7647 { # case insensitive seach on windows
7648 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7649 next;
7650 }
7651 }
7652 elsif($OSgroup eq "macos")
7653 { # seach in frameworks
7654 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7655 {
7656 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7657 {# frameworks
7658 my ($HFramework, $HName) = ($1, $2);
7659 $Dep = $HFramework;
7660 }
7661 else
7662 {# mismatch
7663 next;
7664 }
7665 }
7666 }
7667 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7668 { # Linux, FreeBSD
7669 next;
7670 }
7671 }
7672 if(not $Dep)
7673 { # nothing to include
7674 next;
7675 }
7676 if(is_default_include_dir($Dep))
7677 { # included by the compiler
7678 next;
7679 }
7680 if(get_depth($Dep)==1)
7681 { # too short
7682 next;
7683 }
7684 if(isLibcDir($Dep))
7685 { # do NOT include /usr/include/{sys,bits}
7686 next;
7687 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007688 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007689 }
7690 }
7691 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7692 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7693}
7694
7695sub sortIncPaths($$)
7696{
7697 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007698 if(not $ArrRef or $#{$ArrRef}<0) {
7699 return $ArrRef;
7700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007701 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7702 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007703 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007704 return $ArrRef;
7705}
7706
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007707sub sortDeps($$$)
7708{
7709 if($Header_Dependency{$_[2]}{$_[0]}
7710 and not $Header_Dependency{$_[2]}{$_[1]}) {
7711 return 1;
7712 }
7713 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7714 and $Header_Dependency{$_[2]}{$_[1]}) {
7715 return -1;
7716 }
7717 return 0;
7718}
7719
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007720sub join_P($$)
7721{
7722 my $S = "/";
7723 if($OSgroup eq "windows") {
7724 $S = "\\";
7725 }
7726 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007727}
7728
7729sub get_namespace_additions($)
7730{
7731 my $NameSpaces = $_[0];
7732 my ($Additions, $AddNameSpaceId) = ("", 1);
7733 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7734 {
7735 next if($SkipNameSpaces{$Version}{$NS});
7736 next if(not $NS or $NameSpaces->{$NS}==-1);
7737 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7738 next if($NS=~/\A__/i);
7739 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007740 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007741 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7742 my @NS_Parts = split(/::/, $NS);
7743 next if($#NS_Parts==-1);
7744 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7745 foreach my $NS_Part (@NS_Parts)
7746 {
7747 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7748 $TypeDecl_Suffix .= "}";
7749 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007750 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007751 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7752 $Additions.=" $TypeDecl\n $FuncDecl\n";
7753 $AddNameSpaceId+=1;
7754 }
7755 return $Additions;
7756}
7757
7758sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007759{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007760 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007761 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007762 if($Fmt eq "windows")
7763 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007764 $Path=~s/\//\\/g;
7765 $Path=lc($Path);
7766 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007767 else
7768 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007769 $Path=~s/\\/\//g;
7770 }
7771 return $Path;
7772}
7773
7774sub inc_opt($$)
7775{
7776 my ($Path, $Style) = @_;
7777 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007778 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007779 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007780 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007781 return "-I\"".path_format($Path, "unix")."\"";
7782 }
7783 elsif($OSgroup eq "macos"
7784 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007785 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007786 return "-F".esc(get_dirname($Path));
7787 }
7788 else {
7789 return "-I".esc($Path);
7790 }
7791 }
7792 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007793 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007794 }
7795 return "";
7796}
7797
7798sub platformSpecs($)
7799{
7800 my $LibVersion = $_[0];
7801 my $Arch = getArch($LibVersion);
7802 if($OStarget eq "symbian")
7803 { # options for GCCE compiler
7804 my %Symbian_Opts = map {$_=>1} (
7805 "-D__GCCE__",
7806 "-DUNICODE",
7807 "-fexceptions",
7808 "-D__SYMBIAN32__",
7809 "-D__MARM_INTERWORK__",
7810 "-D_UNICODE",
7811 "-D__S60_50__",
7812 "-D__S60_3X__",
7813 "-D__SERIES60_3X__",
7814 "-D__EPOC32__",
7815 "-D__MARM__",
7816 "-D__EABI__",
7817 "-D__MARM_ARMV5__",
7818 "-D__SUPPORT_CPP_EXCEPTIONS__",
7819 "-march=armv5t",
7820 "-mapcs",
7821 "-mthumb-interwork",
7822 "-DEKA2",
7823 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7824 );
7825 return join(" ", keys(%Symbian_Opts));
7826 }
7827 elsif($OSgroup eq "windows"
7828 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7829 { # add options to MinGW compiler
7830 # to simulate the MSVC compiler
7831 my %MinGW_Opts = map {$_=>1} (
7832 "-D_WIN32",
7833 "-D_STDCALL_SUPPORTED",
7834 "-D__int64=\"long long\"",
7835 "-D__int32=int",
7836 "-D__int16=short",
7837 "-D__int8=char",
7838 "-D__possibly_notnullterminated=\" \"",
7839 "-D__nullterminated=\" \"",
7840 "-D__nullnullterminated=\" \"",
7841 "-D__w64=\" \"",
7842 "-D__ptr32=\" \"",
7843 "-D__ptr64=\" \"",
7844 "-D__forceinline=inline",
7845 "-D__inline=inline",
7846 "-D__uuidof(x)=IID()",
7847 "-D__try=",
7848 "-D__except(x)=",
7849 "-D__declspec(x)=__attribute__((x))",
7850 "-D__pragma(x)=",
7851 "-D_inline=inline",
7852 "-D__forceinline=__inline",
7853 "-D__stdcall=__attribute__((__stdcall__))",
7854 "-D__cdecl=__attribute__((__cdecl__))",
7855 "-D__fastcall=__attribute__((__fastcall__))",
7856 "-D__thiscall=__attribute__((__thiscall__))",
7857 "-D_stdcall=__attribute__((__stdcall__))",
7858 "-D_cdecl=__attribute__((__cdecl__))",
7859 "-D_fastcall=__attribute__((__fastcall__))",
7860 "-D_thiscall=__attribute__((__thiscall__))",
7861 "-DSHSTDAPI_(x)=x",
7862 "-D_MSC_EXTENSIONS",
7863 "-DSECURITY_WIN32",
7864 "-D_MSC_VER=1500",
7865 "-D_USE_DECLSPECS_FOR_SAL",
7866 "-D__noop=\" \"",
7867 "-DDECLSPEC_DEPRECATED=\" \"",
7868 "-D__builtin_alignof(x)=__alignof__(x)",
7869 "-DSORTPP_PASS");
7870 if($Arch eq "x86") {
7871 $MinGW_Opts{"-D_M_IX86=300"}=1;
7872 }
7873 elsif($Arch eq "x86_64") {
7874 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7875 }
7876 elsif($Arch eq "ia64") {
7877 $MinGW_Opts{"-D_M_IA64=300"}=1;
7878 }
7879 return join(" ", keys(%MinGW_Opts));
7880 }
7881 return "";
7882}
7883
7884my %C_Structure = map {$_=>1} (
7885# FIXME: Can't separate union and struct data types before dumping,
7886# so it sometimes cause compilation errors for unknown reason
7887# when trying to declare TYPE* tmp_add_class_N
7888# This is a list of such structures + list of other C structures
7889 "sigval",
7890 "sigevent",
7891 "sigaction",
7892 "sigvec",
7893 "sigstack",
7894 "timeval",
7895 "timezone",
7896 "rusage",
7897 "rlimit",
7898 "wait",
7899 "flock",
7900 "stat",
7901 "_stat",
7902 "stat32",
7903 "_stat32",
7904 "stat64",
7905 "_stat64",
7906 "_stati64",
7907 "if_nameindex",
7908 "usb_device",
7909 "sigaltstack",
7910 "sysinfo",
7911 "timeLocale",
7912 "tcp_debug",
7913 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007914 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007915 "timespec",
7916 "random_data",
7917 "drand48_data",
7918 "_IO_marker",
7919 "_IO_FILE",
7920 "lconv",
7921 "sched_param",
7922 "tm",
7923 "itimerspec",
7924 "_pthread_cleanup_buffer",
7925 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007926 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007927 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007928 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007929 "sigcontext",
7930 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007931 # Mac
7932 "_timex",
7933 "_class_t",
7934 "_category_t",
7935 "_class_ro_t",
7936 "_protocol_t",
7937 "_message_ref_t",
7938 "_super_message_ref_t",
7939 "_ivar_t",
7940 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007941);
7942
7943sub getCompileCmd($$$)
7944{
7945 my ($Path, $Opt, $Inc) = @_;
7946 my $GccCall = $GCC_PATH;
7947 if($Opt) {
7948 $GccCall .= " ".$Opt;
7949 }
7950 $GccCall .= " -x ";
7951 if($OSgroup eq "macos") {
7952 $GccCall .= "objective-";
7953 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007954
7955 if($EMERGENCY_MODE_48)
7956 { # workaround for GCC 4.8 (C only)
7957 $GccCall .= "c++";
7958 }
7959 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007960 { # compile as "C++" header
7961 # to obtain complete dump using GCC 4.0
7962 $GccCall .= "c++-header";
7963 }
7964 else
7965 { # compile as "C++" source
7966 # GCC 3.3 cannot compile headers
7967 $GccCall .= "c++";
7968 }
7969 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007970 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 $GccCall .= " ".$Opts;
7972 }
7973 # allow extra qualifications
7974 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007975 $GccCall .= " -fpermissive";
7976 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007977 if($NoStdInc)
7978 {
7979 $GccCall .= " -nostdinc";
7980 $GccCall .= " -nostdinc++";
7981 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007982 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007983 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007984 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007985 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007986 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007987 if($Inc)
7988 { # include paths
7989 $GccCall .= " ".$Inc;
7990 }
7991 return $GccCall;
7992}
7993
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007994sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007995{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007996 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007997 my %HeaderElems = (
7998 # Types
7999 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008000 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008001 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8002 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008003 "time.h" => ["time_t"],
8004 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008005 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8006 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008007 "stdbool.h" => ["_Bool"],
8008 "rpc/xdr.h" => ["bool_t"],
8009 "in_systm.h" => ["n_long", "n_short"],
8010 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008011 "arpa/inet.h" => ["fw_src", "ip_src"],
8012 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008013 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008014 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008015 );
8016 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008017 foreach (keys(%HeaderElems))
8018 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008019 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008020 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008021 }
8022 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008023 my %Types = ();
8024 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8025 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008026 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008027 }
8028 if(keys(%Types))
8029 {
8030 my %AddHeaders = ();
8031 foreach my $Type (keys(%Types))
8032 {
8033 if(my $Header = $AutoPreamble{$Type})
8034 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008035 if(my $Path = identifyHeader($Header, $LibVersion))
8036 {
8037 if(skipHeader($Path, $LibVersion)) {
8038 next;
8039 }
8040 $Path = path_format($Path, $OSgroup);
8041 $AddHeaders{$Path}{"Type"} = $Type;
8042 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008043 }
8044 }
8045 }
8046 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008047 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008048 }
8049 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008050 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008051}
8052
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008053sub checkCTags($)
8054{
8055 my $Path = $_[0];
8056 if(not $Path) {
8057 return;
8058 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008059 my $CTags = undef;
8060
8061 if($OSgroup eq "bsd")
8062 { # use ectags on BSD
8063 $CTags = get_CmdPath("ectags");
8064 if(not $CTags) {
8065 printMsg("WARNING", "can't find \'ectags\' program");
8066 }
8067 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008068 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008069 $CTags = get_CmdPath("ctags");
8070 }
8071 if(not $CTags)
8072 {
8073 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008074 return;
8075 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008076
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008077 if($OSgroup ne "linux")
8078 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008079 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8080 if($Info!~/exuberant/i)
8081 {
8082 printMsg("WARNING", "incompatible version of \'ctags\' program");
8083 return;
8084 }
8085 }
8086
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008087 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008088 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008089 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008090 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008091 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008092 open(CTAGS, "<", $Out);
8093 while(my $Line = <CTAGS>)
8094 {
8095 chomp($Line);
8096 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008097 if(defined $Intrinsic_Keywords{$Name})
8098 { # noise
8099 next;
8100 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008101 if($Type eq "n")
8102 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008103 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008104 next;
8105 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008106 if(index($Scpe, "struct:")==0) {
8107 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008108 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008109 if(index($Scpe, "namespace:")==0)
8110 {
8111 if($Scpe=~s/\Anamespace://) {
8112 $Name = $Scpe."::".$Name;
8113 }
8114 }
8115 $TUnit_NameSpaces{$Version}{$Name} = 1;
8116 }
8117 elsif($Type eq "p")
8118 {
8119 if(not $Scpe or index($Scpe, "namespace:")==0) {
8120 $TUnit_Funcs{$Version}{$Name} = 1;
8121 }
8122 }
8123 elsif($Type eq "x")
8124 {
8125 if(not $Scpe or index($Scpe, "namespace:")==0) {
8126 $TUnit_Vars{$Version}{$Name} = 1;
8127 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008128 }
8129 }
8130 close(CTAGS);
8131}
8132
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008133sub preChange($$)
8134{
8135 my ($HeaderPath, $IncStr) = @_;
8136
8137 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8138 my $Content = undef;
8139
8140 if($OStarget eq "windows"
8141 and get_dumpmachine($GCC_PATH)=~/mingw/i
8142 and $MinGWMode{$Version}!=-1)
8143 { # modify headers to compile by MinGW
8144 if(not $Content)
8145 { # preprocessing
8146 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8147 }
8148 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8149 { # __asm { ... }
8150 $MinGWMode{$Version}=1;
8151 }
8152 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8153 { # comments after preprocessing
8154 $MinGWMode{$Version}=1;
8155 }
8156 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8157 { # 0xffui8
8158 $MinGWMode{$Version}=1;
8159 }
8160
8161 if($MinGWMode{$Version}) {
8162 printMsg("INFO", "Using MinGW compatibility mode");
8163 }
8164 }
8165
8166 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8167 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8168 { # rename C++ keywords in C code
8169 # disable this code by -cpp-compatible option
8170 if(not $Content)
8171 { # preprocessing
8172 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8173 }
8174 my $RegExp_C = join("|", keys(%CppKeywords_C));
8175 my $RegExp_F = join("|", keys(%CppKeywords_F));
8176 my $RegExp_O = join("|", keys(%CppKeywords_O));
8177
8178 my $Detected = undef;
8179
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008180 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 +04008181 { # MATCH:
8182 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008183 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008184 # unsigned private: 8;
8185 # DO NOT MATCH:
8186 # #pragma GCC visibility push(default)
8187 $CppMode{$Version} = 1;
8188 $Detected = "$1$2$3$4" if(not defined $Detected);
8189 }
8190 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8191 { # MATCH:
8192 # int delete(...);
8193 # int explicit(...);
8194 # DO NOT MATCH:
8195 # void operator delete(...)
8196 $CppMode{$Version} = 1;
8197 $Detected = "$1$2$3" if(not defined $Detected);
8198 }
8199 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8200 { # MATCH:
8201 # int bool;
8202 # DO NOT MATCH:
8203 # bool X;
8204 # return *this;
8205 # throw;
8206 $CppMode{$Version} = 1;
8207 $Detected = "$1$2$3" if(not defined $Detected);
8208 }
8209 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8210 { # MATCH:
8211 # int operator(...);
8212 # DO NOT MATCH:
8213 # int operator()(...);
8214 $CppMode{$Version} = 1;
8215 $Detected = "$1$2$3" if(not defined $Detected);
8216 }
8217 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8218 { # MATCH:
8219 # int foo(int operator);
8220 # int foo(int operator, int other);
8221 # DO NOT MATCH:
8222 # int operator,(...);
8223 $CppMode{$Version} = 1;
8224 $Detected = "$1$2$3" if(not defined $Detected);
8225 }
8226 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8227 { # MATCH:
8228 # int foo(gboolean *bool);
8229 # DO NOT MATCH:
8230 # void setTabEnabled(int index, bool);
8231 $CppMode{$Version} = 1;
8232 $Detected = "$1$2$3" if(not defined $Detected);
8233 }
8234 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8235 { # MATCH:
8236 # int foo(int* this);
8237 # int bar(int this);
8238 # int baz(int throw);
8239 # DO NOT MATCH:
8240 # foo(X, this);
8241 $CppMode{$Version} = 1;
8242 $Detected = "$1$2$3$4" if(not defined $Detected);
8243 }
8244 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8245 { # MATCH:
8246 # struct template {...};
8247 # extern template foo(...);
8248 $CppMode{$Version} = 1;
8249 $Detected = "$1$2" if(not defined $Detected);
8250 }
8251
8252 if($CppMode{$Version} == 1)
8253 {
8254 if($Debug)
8255 {
8256 $Detected=~s/\A\s+//g;
8257 printMsg("INFO", "Detected code: \"$Detected\"");
8258 }
8259 }
8260
8261 # remove typedef enum NAME NAME;
8262 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8263 my $N = 0;
8264 while($N<=$#FwdTypedefs-1)
8265 {
8266 my $S = $FwdTypedefs[$N];
8267 if($S eq $FwdTypedefs[$N+1])
8268 {
8269 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008270 $CppMode{$Version} = 1;
8271
8272 if($Debug) {
8273 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8274 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008275 }
8276 $N+=2;
8277 }
8278
8279 if($CppMode{$Version}==1) {
8280 printMsg("INFO", "Using C++ compatibility mode");
8281 }
8282 }
8283
8284 if($CppMode{$Version}==1
8285 or $MinGWMode{$Version}==1)
8286 {
8287 my $IPath = $TMP_DIR."/dump$Version.i";
8288 writeFile($IPath, $Content);
8289 return $IPath;
8290 }
8291
8292 return undef;
8293}
8294
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008295sub getDump()
8296{
8297 if(not $GCC_PATH) {
8298 exitStatus("Error", "internal error - GCC path is not set");
8299 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008300
8301 my @Headers = keys(%{$Registered_Headers{$Version}});
8302 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8303
8304 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8305
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008306 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008307 my $HeaderPath = $TmpHeaderPath;
8308
8309 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008310 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008311 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8312 {
8313 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008314 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008316 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008317 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8318 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008319 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008320 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008321 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008322 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8323 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008325 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008326 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008327
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008328 if($ExtraInfo)
8329 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008330 if($IncludeString) {
8331 writeFile($ExtraInfo."/include-string", $IncludeString);
8332 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008333 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8334 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008335
8336 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8337 {
8338 my $REDIR = "";
8339 foreach my $P1 (sort @Redirects) {
8340 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8341 }
8342 writeFile($ExtraInfo."/include-redirect", $REDIR);
8343 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008344 }
8345
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008346 if(not keys(%{$TargetHeaders{$Version}}))
8347 { # Target headers
8348 addTargetHeaders($Version);
8349 }
8350
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008351 # clean memory
8352 %RecursiveIncludes = ();
8353 %Header_Include_Prefix = ();
8354 %Header_Includes = ();
8355
8356 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008357 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008358 delete($Cache{"detect_header_includes"});
8359 delete($Cache{"selectSystemHeader"});
8360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008361 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008362 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8363 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008364
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008365 if($ExtraInfo)
8366 { # extra information for other tools
8367 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8368 }
8369
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008370 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008371 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008372 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008373
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008374 if($COMMON_LANGUAGE{$Version} eq "C++") {
8375 checkCTags($Pre);
8376 }
8377
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008378 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8379 { # try to correct the preprocessor output
8380 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008381 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008383 if($COMMON_LANGUAGE{$Version} eq "C++")
8384 { # add classes and namespaces to the dump
8385 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008386 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008387 or $MinGWMode{$Version}==1) {
8388 $CHdump .= " -fpreprocessed";
8389 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008390 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008391 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008392 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008393 chdir($ORIG_DIR);
8394 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8395 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008396 my $Content = readFile($ClassDump);
8397 foreach my $ClassInfo (split(/\n\n/, $Content))
8398 {
8399 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8400 {
8401 my $CName = $1;
8402 next if($CName=~/\A(__|_objc_|_opaque_)/);
8403 $TUnit_NameSpaces{$Version}{$CName} = -1;
8404 if($CName=~/\A[\w:]+\Z/)
8405 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008406 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008407 }
8408 if($CName=~/(\w[\w:]*)::/)
8409 { # namespaces
8410 my $NS = $1;
8411 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8412 $TUnit_NameSpaces{$Version}{$NS} = 1;
8413 }
8414 }
8415 }
8416 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8417 { # read v-tables (advanced approach)
8418 my ($CName, $VTable) = ($1, $2);
8419 $ClassVTable_Content{$Version}{$CName} = $VTable;
8420 }
8421 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008422 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8423 { # add user-defined namespaces
8424 $TUnit_NameSpaces{$Version}{$NS} = 1;
8425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008426 if($Debug)
8427 { # debug mode
8428 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008429 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008430 }
8431 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008432 }
8433
8434 # add namespaces and classes
8435 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8436 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008437 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008438 }
8439 # some GCC versions don't include class methods to the TU dump by default
8440 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008441 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008442 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8443 {
8444 next if($C_Structure{$CName});
8445 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008446 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008447 if(not $Force and $GCC_44
8448 and $OSgroup eq "linux")
8449 { # optimization for linux with GCC >= 4.4
8450 # disable this code by -force option
8451 if(index($CName, "::")!=-1)
8452 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008453 next;
8454 }
8455 }
8456 else
8457 {
8458 if($CName=~/\A(.+)::[^:]+\Z/
8459 and $TUnit_Classes{$Version}{$1})
8460 { # classes inside other classes
8461 next;
8462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008464 if(defined $TUnit_Funcs{$Version}{$CName})
8465 { # the same name for a function and type
8466 next;
8467 }
8468 if(defined $TUnit_Vars{$Version}{$CName})
8469 { # the same name for a variable and type
8470 next;
8471 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008472 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8473 }
8474 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008475 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008476 }
8477 }
8478 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8479 # create TU dump
8480 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008481 if($UserLang eq "C") {
8482 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8483 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008484 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008485 or $MinGWMode{$Version}==1) {
8486 $TUdump .= " -fpreprocessed";
8487 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008488 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008489 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8490 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008491 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008492 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008493 if($?)
8494 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008495 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008496 { # try to recompile
8497 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008498 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008499 and index($Errors, "c99_")!=-1
8500 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008501 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008502 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008503
8504 if($Debug)
8505 {
8506 # printMsg("INFO", $Errors);
8507 }
8508
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008509 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 resetLogging($Version);
8511 $TMP_DIR = tempdir(CLEANUP=>1);
8512 return getDump();
8513 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008514 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008515 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008516 { # add auto preamble headers and try again
8517 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008518 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008519 foreach my $Num (0 .. $#Headers)
8520 {
8521 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008522 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8523 {
8524 push_U($Include_Preamble{$Version}, $Path);
8525 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008526 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008527 }
8528 resetLogging($Version);
8529 $TMP_DIR = tempdir(CLEANUP=>1);
8530 return getDump();
8531 }
8532 elsif($Cpp0xMode{$Version}!=-1
8533 and ($Errors=~/\Q-std=c++0x\E/
8534 or $Errors=~/is not a class or namespace/))
8535 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008536 if(check_gcc($GCC_PATH, "4.6"))
8537 {
8538 $Cpp0xMode{$Version}=-1;
8539 printMsg("INFO", "Enabling c++0x mode");
8540 resetLogging($Version);
8541 $TMP_DIR = tempdir(CLEANUP=>1);
8542 $CompilerOptions{$Version} .= " -std=c++0x";
8543 return getDump();
8544 }
8545 else {
8546 printMsg("WARNING", "Probably c++0x construction detected");
8547 }
8548
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008549 }
8550 elsif($MinGWMode{$Version}==1)
8551 { # disable MinGW mode and try again
8552 $MinGWMode{$Version}=-1;
8553 resetLogging($Version);
8554 $TMP_DIR = tempdir(CLEANUP=>1);
8555 return getDump();
8556 }
8557 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008558 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008559 else {
8560 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008561 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008562 printMsg("ERROR", "some errors occurred when compiling headers");
8563 printErrorLog($Version);
8564 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008565 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008566 }
8567 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008568 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008569 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008570
8571 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8572 return $TUs[0];
8573 }
8574 else
8575 {
8576 my $Msg = "can't compile header(s)";
8577 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8578 $Msg .= "\nDid you install G++?";
8579 }
8580 exitStatus("Cannot_Compile", $Msg);
8581 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008582}
8583
8584sub cmd_file($)
8585{
8586 my $Path = $_[0];
8587 return "" if(not $Path or not -e $Path);
8588 if(my $CmdPath = get_CmdPath("file")) {
8589 return `$CmdPath -b \"$Path\"`;
8590 }
8591 return "";
8592}
8593
8594sub getIncString($$)
8595{
8596 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008597 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008598 my $String = "";
8599 foreach (@{$ArrRef}) {
8600 $String .= " ".inc_opt($_, $Style);
8601 }
8602 return $String;
8603}
8604
8605sub getIncPaths(@)
8606{
8607 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008608 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008609 if($INC_PATH_AUTODETECT{$Version})
8610 { # auto-detecting dependencies
8611 my %Includes = ();
8612 foreach my $HPath (@HeaderPaths)
8613 {
8614 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8615 {
8616 if($Skip_Include_Paths{$Version}{$Dir}) {
8617 next;
8618 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008619 if($SystemRoot)
8620 {
8621 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8622 next;
8623 }
8624 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008625 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008626 }
8627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008628 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008629 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008630 }
8631 }
8632 else
8633 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008634 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008635 }
8636 return \@IncPaths;
8637}
8638
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008639sub push_U($@)
8640{ # push unique
8641 if(my $Array = shift @_)
8642 {
8643 if(@_)
8644 {
8645 my %Exist = map {$_=>1} @{$Array};
8646 foreach my $Elem (@_)
8647 {
8648 if(not defined $Exist{$Elem})
8649 {
8650 push(@{$Array}, $Elem);
8651 $Exist{$Elem} = 1;
8652 }
8653 }
8654 }
8655 }
8656}
8657
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008658sub callPreprocessor($$$)
8659{
8660 my ($Path, $Inc, $LibVersion) = @_;
8661 return "" if(not $Path or not -f $Path);
8662 my $IncludeString=$Inc;
8663 if(not $Inc) {
8664 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8665 }
8666 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008667 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008668 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008669 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670}
8671
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008672sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673{ # native "find" is much faster than File::Find (~6x)
8674 # also the File::Find doesn't support --maxdepth N option
8675 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008676 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677 return () if(not $Path or not -e $Path);
8678 if($OSgroup eq "windows")
8679 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008680 $Path = get_abs_path($Path);
8681 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008682 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008683 if($MaxDepth!=1) {
8684 $Cmd .= " /S";
8685 }
8686 if($Type eq "d") {
8687 $Cmd .= " /AD";
8688 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008689 elsif($Type eq "f") {
8690 $Cmd .= " /A-D";
8691 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008692 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008694 {
8695 if(not $UseRegex)
8696 { # FIXME: how to search file names in MS shell?
8697 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008698 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008699 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008700 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008701 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008702 }
8703 my @AbsPaths = ();
8704 foreach my $File (@Files)
8705 {
8706 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008707 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008708 }
8709 if($Type eq "f" and not -f $File)
8710 { # skip dirs
8711 next;
8712 }
8713 push(@AbsPaths, path_format($File, $OSgroup));
8714 }
8715 if($Type eq "d") {
8716 push(@AbsPaths, $Path);
8717 }
8718 return @AbsPaths;
8719 }
8720 else
8721 {
8722 my $FindCmd = get_CmdPath("find");
8723 if(not $FindCmd) {
8724 exitStatus("Not_Found", "can't find a \"find\" command");
8725 }
8726 $Path = get_abs_path($Path);
8727 if(-d $Path and -l $Path
8728 and $Path!~/\/\Z/)
8729 { # for directories that are symlinks
8730 $Path.="/";
8731 }
8732 my $Cmd = $FindCmd." \"$Path\"";
8733 if($MaxDepth) {
8734 $Cmd .= " -maxdepth $MaxDepth";
8735 }
8736 if($Type) {
8737 $Cmd .= " -type $Type";
8738 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008739 if($Name and not $UseRegex)
8740 { # wildcards
8741 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008743 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008744 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008745 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8746 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008747 my @Files = split(/\n/, $Res);
8748 if($Name and $UseRegex)
8749 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008750 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008751 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008752 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008753 }
8754}
8755
8756sub unpackDump($)
8757{
8758 my $Path = $_[0];
8759 return "" if(not $Path or not -e $Path);
8760 $Path = get_abs_path($Path);
8761 $Path = path_format($Path, $OSgroup);
8762 my ($Dir, $FileName) = separate_path($Path);
8763 my $UnpackDir = $TMP_DIR."/unpack";
8764 rmtree($UnpackDir);
8765 mkpath($UnpackDir);
8766 if($FileName=~s/\Q.zip\E\Z//g)
8767 { # *.zip
8768 my $UnzipCmd = get_CmdPath("unzip");
8769 if(not $UnzipCmd) {
8770 exitStatus("Not_Found", "can't find \"unzip\" command");
8771 }
8772 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008773 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008774 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008775 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776 }
8777 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008778 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 if(not @Contents) {
8780 exitStatus("Error", "can't extract \'$Path\'");
8781 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008782 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008783 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008784 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008785 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008786 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008787 if($OSgroup eq "windows")
8788 { # -xvzf option is not implemented in tar.exe (2003)
8789 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8790 my $TarCmd = get_CmdPath("tar");
8791 if(not $TarCmd) {
8792 exitStatus("Not_Found", "can't find \"tar\" command");
8793 }
8794 my $GzipCmd = get_CmdPath("gzip");
8795 if(not $GzipCmd) {
8796 exitStatus("Not_Found", "can't find \"gzip\" command");
8797 }
8798 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008799 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 if($?) {
8801 exitStatus("Error", "can't extract \'$Path\'");
8802 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008803 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008804 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008805 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008806 }
8807 chdir($ORIG_DIR);
8808 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008809 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 if(not @Contents) {
8811 exitStatus("Error", "can't extract \'$Path\'");
8812 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008813 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008814 }
8815 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008816 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008817 my $TarCmd = get_CmdPath("tar");
8818 if(not $TarCmd) {
8819 exitStatus("Not_Found", "can't find \"tar\" command");
8820 }
8821 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008822 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008823 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008824 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008825 }
8826 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008827 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008828 if(not @Contents) {
8829 exitStatus("Error", "can't extract \'$Path\'");
8830 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008831 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
8833 }
8834}
8835
8836sub createArchive($$)
8837{
8838 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008839 if(not $To) {
8840 $To = ".";
8841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008842 if(not $Path or not -e $Path
8843 or not -d $To) {
8844 return "";
8845 }
8846 my ($From, $Name) = separate_path($Path);
8847 if($OSgroup eq "windows")
8848 { # *.zip
8849 my $ZipCmd = get_CmdPath("zip");
8850 if(not $ZipCmd) {
8851 exitStatus("Not_Found", "can't find \"zip\"");
8852 }
8853 my $Pkg = $To."/".$Name.".zip";
8854 unlink($Pkg);
8855 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008856 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008857 if($?)
8858 { # cannot allocate memory (or other problems with "zip")
8859 unlink($Path);
8860 exitStatus("Error", "can't pack the ABI dump: ".$!);
8861 }
8862 chdir($ORIG_DIR);
8863 unlink($Path);
8864 return $Pkg;
8865 }
8866 else
8867 { # *.tar.gz
8868 my $TarCmd = get_CmdPath("tar");
8869 if(not $TarCmd) {
8870 exitStatus("Not_Found", "can't find \"tar\"");
8871 }
8872 my $GzipCmd = get_CmdPath("gzip");
8873 if(not $GzipCmd) {
8874 exitStatus("Not_Found", "can't find \"gzip\"");
8875 }
8876 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8877 unlink($Pkg);
8878 chdir($From);
8879 system($TarCmd, "-czf", $Pkg, $Name);
8880 if($?)
8881 { # cannot allocate memory (or other problems with "tar")
8882 unlink($Path);
8883 exitStatus("Error", "can't pack the ABI dump: ".$!);
8884 }
8885 chdir($ORIG_DIR);
8886 unlink($Path);
8887 return $To."/".$Name.".tar.gz";
8888 }
8889}
8890
8891sub is_header_file($)
8892{
8893 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8894 return $_[0];
8895 }
8896 return 0;
8897}
8898
8899sub is_not_header($)
8900{
8901 if($_[0]=~/\.\w+\Z/
8902 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8903 return 1;
8904 }
8905 return 0;
8906}
8907
8908sub is_header($$$)
8909{
8910 my ($Header, $UserDefined, $LibVersion) = @_;
8911 return 0 if(-d $Header);
8912 if(-f $Header) {
8913 $Header = get_abs_path($Header);
8914 }
8915 else
8916 {
8917 if(is_abs($Header))
8918 { # incorrect absolute path
8919 return 0;
8920 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008921 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008922 $Header = $HPath;
8923 }
8924 else
8925 { # can't find header
8926 return 0;
8927 }
8928 }
8929 if($Header=~/\.\w+\Z/)
8930 { # have an extension
8931 return is_header_file($Header);
8932 }
8933 else
8934 {
8935 if($UserDefined==2)
8936 { # specified on the command line
8937 if(cmd_file($Header)!~/HTML|XML/i) {
8938 return $Header;
8939 }
8940 }
8941 elsif($UserDefined)
8942 { # specified in the XML-descriptor
8943 # header file without an extension
8944 return $Header;
8945 }
8946 else
8947 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008948 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008949 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008950 { # !~/HTML|XML|shared|dynamic/i
8951 return $Header;
8952 }
8953 }
8954 }
8955 return 0;
8956}
8957
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008958sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008959{
8960 my $LibVersion = $_[0];
8961 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8962 {
8963 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008964 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008965
8966 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8967 detect_recursive_includes($RegHeader, $LibVersion);
8968 }
8969
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008970 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8971 {
8972 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008973
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008974 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008975 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8976 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008977 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008978 }
8979 }
8980 }
8981}
8982
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008983sub familiarDirs($$)
8984{
8985 my ($D1, $D2) = @_;
8986 if($D1 eq $D2) {
8987 return 1;
8988 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008989
8990 my $U1 = index($D1, "/usr/");
8991 my $U2 = index($D2, "/usr/");
8992
8993 if($U1==0 and $U2!=0) {
8994 return 0;
8995 }
8996
8997 if($U2==0 and $U1!=0) {
8998 return 0;
8999 }
9000
9001 if(index($D2, $D1."/")==0) {
9002 return 1;
9003 }
9004
9005 # /usr/include/DIR
9006 # /home/user/DIR
9007
9008 my $DL = get_depth($D1);
9009
9010 my @Dirs1 = ($D1);
9011 while($DL - get_depth($D1)<=2
9012 and get_depth($D1)>=4
9013 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9014 push(@Dirs1, $D1);
9015 }
9016
9017 my @Dirs2 = ($D2);
9018 while(get_depth($D2)>=4
9019 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9020 push(@Dirs2, $D2);
9021 }
9022
9023 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009024 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009025 foreach my $P2 (@Dirs2)
9026 {
9027
9028 if($P1 eq $P2) {
9029 return 1;
9030 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009031 }
9032 }
9033 return 0;
9034}
9035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009036sub readHeaders($)
9037{
9038 $Version = $_[0];
9039 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9040 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009041 if($Debug)
9042 { # debug mode
9043 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009044 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009045 }
9046 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009047}
9048
9049sub prepareTypes($)
9050{
9051 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009052 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009053 { # support for old ABI dumps
9054 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009055 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009056 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009057 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9058 if($TName=~/\A(\w+)::(\w+)/) {
9059 my ($P1, $P2) = ($1, $2);
9060 if($P1 eq $P2) {
9061 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009063 else {
9064 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009066 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009067 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009068 }
9069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009070 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071 { # support for old ABI dumps
9072 # V < 2.5: array size == "number of elements"
9073 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009074 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009075 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009076 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009077 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009078 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009079 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009080 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009081 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009082 $Size *= $Base{"Size"};
9083 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009084 }
9085 else
9086 { # array[] is a pointer
9087 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009088 }
9089 }
9090 }
9091 }
9092 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009093 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009094 { # support for old ABI dumps
9095 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009096 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009097 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009098 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009099 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009100 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009101 my %Type = get_Type($TypeId, $LibVersion);
9102 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9103 my %Type2 = get_Type($TypeId_2, $V2);
9104 if($Type{"Size"} ne $Type2{"Size"}) {
9105 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009106 }
9107 }
9108 }
9109 }
9110}
9111
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009112sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009113{
9114 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009115
9116 if(not keys(%{$SymbolInfo{$LibVersion}}))
9117 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009118 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009119 {
9120 if($CheckHeadersOnly) {
9121 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9122 }
9123 else {
9124 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9125 }
9126 }
9127 }
9128
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009129 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009130 if(not checkDump(1, "2.10")
9131 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009132 { # different formats
9133 $Remangle = 1;
9134 }
9135 if($CheckHeadersOnly)
9136 { # different languages
9137 if($UserLang)
9138 { # --lang=LANG for both versions
9139 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9140 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9141 {
9142 if($UserLang eq "C++")
9143 { # remangle symbols
9144 $Remangle = 1;
9145 }
9146 elsif($UserLang eq "C")
9147 { # remove mangling
9148 $Remangle = -1;
9149 }
9150 }
9151 }
9152 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009153
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009154 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009155 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009156 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009157 { # support for old ABI dumps
9158 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9159 {
9160 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9161 {
9162 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9163 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009164 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009165 if(defined $DVal and $DVal ne "")
9166 {
9167 if($TName eq "char") {
9168 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9169 }
9170 elsif($TName eq "bool") {
9171 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9172 }
9173 }
9174 }
9175 }
9176 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009177 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009178 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009179 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9180 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009181 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009182 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9183 # + support for old ABI dumps
9184 next;
9185 }
9186 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009187 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009188 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009189 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009190 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009191
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009192 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009193 if(not checkDump(1, "2.12")
9194 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009195 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009196 if($ShortName eq "operator>>")
9197 {
9198 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9199 { # corrected mangling of operator>>
9200 $SRemangle = 1;
9201 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009202 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009203 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9204 {
9205 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9206 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9207 { # corrected mangling of const global data
9208 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9209 # and incorrectly mangled by old ACC versions
9210 $SRemangle = 1;
9211 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009212 }
9213 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009214 if(not $CheckHeadersOnly)
9215 { # support for old ABI dumps
9216 if(not checkDump(1, "2.17")
9217 or not checkDump(2, "2.17"))
9218 {
9219 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9220 {
9221 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9222 {
9223 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9224 {
9225 $MnglName = $ShortName;
9226 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9227 }
9228 }
9229 }
9230 }
9231 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009232 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009233 { # support for old ABI dumps: some symbols are not mangled in old dumps
9234 # mangle both sets of symbols (old and new)
9235 # NOTE: remangling all symbols by the same mangler
9236 if($MnglName=~/\A_ZN(V|)K/)
9237 { # mangling may be incorrect on old ABI dumps
9238 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009239 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009240 }
9241 if($MnglName=~/\A_ZN(K|)V/)
9242 { # mangling may be incorrect on old ABI dumps
9243 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009244 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009245 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009246 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9247 or (not $ClassID and $CheckHeadersOnly)
9248 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9249 { # support for old ABI dumps, GCC >= 4.0
9250 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009251 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009253 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009254 $MangledNames{$LibVersion}{$MnglName} = 1;
9255 }
9256 }
9257 }
9258 elsif($Remangle==-1)
9259 { # remove mangling
9260 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009261 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009263 if(not $MnglName) {
9264 next;
9265 }
9266 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9267 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009268 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9269
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009271 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 { # support for old dumps
9273 # add "Volatile" attribute
9274 if($MnglName=~/_Z(K|)V/) {
9275 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9276 }
9277 }
9278 # symbol and its symlink have same signatures
9279 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009280 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009282
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009283 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9284 {
9285 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9286 if($SymVer{$LibVersion}{$Alias}) {
9287 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9288 }
9289 }
9290
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009291 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009292 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009293 }
9294 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9295 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9296 }
9297 if($ExtendedCheck)
9298 { # --ext option
9299 addExtension($LibVersion);
9300 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301
9302 # clean memory
9303 delete($SymbolInfo{$LibVersion});
9304
9305 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009306 { # detect allocable classes with public exported constructors
9307 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009308 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009309 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009310 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009311 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009312 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9313 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009315 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009317 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318 $AllocableClass{$LibVersion}{$ClassName} = 1;
9319 }
9320 }
9321 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009322 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009323 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009324 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009325 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009326 if($CheckHeadersOnly)
9327 {
9328 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9329 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9330 { # all symbols except non-virtual inline
9331 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9332 }
9333 }
9334 else {
9335 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009336 }
9337 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009338 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009339 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009340 }
9341 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009342 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009343 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009344 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009345 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009346 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009347 if(defined $Base{"Type"}
9348 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009350 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009351 if($Name=~/<([^<>\s]+)>/)
9352 {
9353 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9354 $ReturnedClass{$LibVersion}{$Tid} = 1;
9355 }
9356 }
9357 else {
9358 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9359 }
9360 }
9361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009363 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009365 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009366 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009367 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009368 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009369 if($Base{"Type"}=~/Struct|Class/)
9370 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009371 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009372 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9373 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009374 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 }
9377 }
9378 }
9379 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009380
9381 # mapping {short name => symbols}
9382 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009384 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009385 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009386 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009388 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009389 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009390 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009392 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009393 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 }
9395 }
9396 }
9397 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009398
9399 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009402 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009403 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009404 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9405 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009407 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009409 $ClassNames{$LibVersion}{$TName} = 1;
9410 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009412 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9413 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 }
9415 }
9416 }
9417 }
9418 }
9419}
9420
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009421sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009422{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009423 my ($Tid, $LibVersion) = @_;
9424 if(not $Tid) {
9425 return $Tid;
9426 }
9427
9428 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9429 {
9430 if($TName_Tid{$LibVersion}{$Name}) {
9431 return $TName_Tid{$LibVersion}{$Name};
9432 }
9433 }
9434
9435 return $Tid;
9436}
9437
9438sub register_SymbolUsage($$$)
9439{
9440 my ($InfoId, $UsedType, $LibVersion) = @_;
9441
9442 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9443 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9444 {
9445 register_TypeUsage($RTid, $UsedType, $LibVersion);
9446 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9447 }
9448 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9449 {
9450 register_TypeUsage($FCid, $UsedType, $LibVersion);
9451 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9452
9453 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9454 { # register "this" pointer
9455 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9456 }
9457 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9458 { # register "this" pointer (const method)
9459 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9460 }
9461 }
9462 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9463 {
9464 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9465 {
9466 register_TypeUsage($PTid, $UsedType, $LibVersion);
9467 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9468 }
9469 }
9470 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9471 {
9472 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9473 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9474 register_TypeUsage($TTid, $UsedType, $LibVersion);
9475 }
9476 }
9477}
9478
9479sub register_TypeUsage($$$)
9480{
9481 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009482 if(not $TypeId) {
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 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009486 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009487 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009488 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009489
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009490 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009491 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009492 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009493 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009494 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009495 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9496 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9497 }
9498 }
9499
9500 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9501 {
9502 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009503 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009504 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009505 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9506 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009507 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009508 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9509 {
9510 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9511 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009512 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009513 }
9514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009516 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009517 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009518 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9519 {
9520 register_TypeUsage($MTid, $UsedType, $LibVersion);
9521 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009522 }
9523 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009524 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009525 or $TInfo{"Type"} eq "MethodPtr"
9526 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009527 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009528 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009529 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009530 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009531 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009532 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009533 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9534 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009535 }
9536 }
9537 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009538 if($TInfo{"Type"} eq "FieldPtr")
9539 {
9540 if(my $RTid = $TInfo{"Return"}) {
9541 register_TypeUsage($RTid, $UsedType, $LibVersion);
9542 }
9543 if(my $CTid = $TInfo{"Class"}) {
9544 register_TypeUsage($CTid, $UsedType, $LibVersion);
9545 }
9546 }
9547 if($TInfo{"Type"} eq "MethodPtr")
9548 {
9549 if(my $CTid = $TInfo{"Class"}) {
9550 register_TypeUsage($CTid, $UsedType, $LibVersion);
9551 }
9552 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009553 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009554 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009555 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009556 $UsedType->{$TypeId} = 1;
9557 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9558 {
9559 register_TypeUsage($BTid, $UsedType, $LibVersion);
9560 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9561 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009562 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009563 else
9564 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9565 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009566 }
9567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009568}
9569
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009570sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009571{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009572 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9573
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009574 if($Level eq "Dump")
9575 {
9576 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9577 { # TODO: check if this symbol is from
9578 # base classes of other target symbols
9579 return 1;
9580 }
9581 }
9582
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009583 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9584 { # stdc++ interfaces
9585 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009586 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009587
9588 my $Target = 0;
9589 if(my $Header = $SInfo->{"Header"}) {
9590 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9591 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009592 if($ExtendedCheck)
9593 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009594 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009595 $Target = 1;
9596 }
9597 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009598 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009599 {
9600 if($Target)
9601 {
9602 if($Level eq "Dump")
9603 { # dumped
9604 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009605 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009606 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009607 return 1;
9608 }
9609 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009610 else {
9611 return 1;
9612 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009613 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009614 elsif($Level eq "Source")
9615 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009616 return 1;
9617 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009618 elsif($Level eq "Binary")
9619 { # checked
9620 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9621 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9622 return 1;
9623 }
9624 }
9625 }
9626 }
9627 else
9628 { # library is available
9629 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9630 { # exported symbols
9631 return 1;
9632 }
9633 if($Level eq "Dump")
9634 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009635 if($BinaryOnly)
9636 {
9637 if($SInfo->{"Data"})
9638 {
9639 if($Target) {
9640 return 1;
9641 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009642 }
9643 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009644 else
9645 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009646 if($Target) {
9647 return 1;
9648 }
9649 }
9650 }
9651 elsif($Level eq "Source")
9652 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009653 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009654 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009655 { # skip LOCAL symbols
9656 if($Target) {
9657 return 1;
9658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009659 }
9660 }
9661 elsif($Level eq "Binary")
9662 { # checked
9663 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9664 {
9665 if($Target) {
9666 return 1;
9667 }
9668 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009669 }
9670 }
9671 return 0;
9672}
9673
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009674sub cleanDump($)
9675{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009676 my $LibVersion = $_[0];
9677 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9678 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009679 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9680 {
9681 delete($SymbolInfo{$LibVersion}{$InfoId});
9682 next;
9683 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009684 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009685 if(not $MnglName)
9686 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009687 delete($SymbolInfo{$LibVersion}{$InfoId});
9688 next;
9689 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009690 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009691 if(not $ShortName)
9692 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009693 delete($SymbolInfo{$LibVersion}{$InfoId});
9694 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009695 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009696 if($MnglName eq $ShortName)
9697 { # remove duplicate data
9698 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009699 }
9700 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9701 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9702 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009703 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9704 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9705 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009706 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009708 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009709 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009710 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9711 {
9712 delete($TypeInfo{$LibVersion}{$Tid});
9713 next;
9714 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009715 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009716 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009717 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009718 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9719 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9720 }
9721 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009722 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9723 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9724 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009725 }
9726}
9727
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009728sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009729{
9730 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009731
9732 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9733 {
9734 if(defined $TypeInfo{$LibVersion}{$Dupl})
9735 {
9736 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9737 { # duplicate
9738 return 0;
9739 }
9740 }
9741 }
9742
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009743 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9744
9745 if(isBuiltIn($THeader)) {
9746 return 0;
9747 }
9748
9749 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9750 return 0;
9751 }
9752
9753 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9754 return 0;
9755 }
9756
9757 if(selfTypedef($Tid, $LibVersion)) {
9758 return 0;
9759 }
9760
9761 if(not isTargetType($Tid, $LibVersion)) {
9762 return 0;
9763 }
9764
9765 return 0;
9766}
9767
9768sub isTargetType($$)
9769{
9770 my ($Tid, $LibVersion) = @_;
9771
9772 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9773 { # derived
9774 return 1;
9775 }
9776
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009777 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9778 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009779 if(not is_target_header($THeader, $LibVersion))
9780 { # from target headers
9781 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782 }
9783 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009784 else {
9785 return 0;
9786 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009787
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009788 if($SkipInternalTypes)
9789 {
9790 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9791 {
9792 return 0;
9793 }
9794 }
9795
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009796 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009797}
9798
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009799sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009800{ # remove unused data types from the ABI dump
9801 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009802
9803 my %UsedType = ();
9804
9805 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009806 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009807 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009808 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009809 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009810 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009811 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009812 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009813 next;
9814 }
9815
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009816 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009817 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009818 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009819 {
9820 my %Tree = ();
9821 register_TypeUsage($Tid, \%Tree, $LibVersion);
9822
9823 my $Tmpl = 0;
9824 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9825 {
9826 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9827 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9828 {
9829 $Tmpl = 1;
9830 last;
9831 }
9832 }
9833 if(not $Tmpl)
9834 {
9835 foreach (keys(%Tree)) {
9836 $UsedType{$_} = 1;
9837 }
9838 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009839 }
9840 }
9841 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009842
9843 my %Delete = ();
9844
9845 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009846 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009847 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009848 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009849 next;
9850 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009851
9852 if($Kind eq "Extra")
9853 {
9854 my %Tree = ();
9855 register_TypeUsage($Tid, \%Tree, $LibVersion);
9856
9857 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9858 {
9859 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9860 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9861 {
9862 $Delete{$Tid} = 1;
9863 last;
9864 }
9865 }
9866 }
9867 else
9868 {
9869 # remove type
9870 delete($TypeInfo{$LibVersion}{$Tid});
9871 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009872 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009873
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009874 if($Kind eq "Extra")
9875 { # remove duplicates
9876 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9877 {
9878 if($UsedType{$Tid})
9879 { # All & Extended
9880 next;
9881 }
9882
9883 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9884
9885 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9886 delete($TypeInfo{$LibVersion}{$Tid});
9887 }
9888 }
9889 }
9890
9891 foreach my $Tid (keys(%Delete))
9892 {
9893 delete($TypeInfo{$LibVersion}{$Tid});
9894 }
9895}
9896
9897sub check_Completeness($$)
9898{
9899 my ($Info, $LibVersion) = @_;
9900
9901 # data types
9902 if(defined $Info->{"Memb"})
9903 {
9904 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9905 {
9906 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9907 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9908 }
9909 }
9910 }
9911 if(defined $Info->{"Base"})
9912 {
9913 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9914 check_TypeInfo($Bid, $LibVersion);
9915 }
9916 }
9917 if(defined $Info->{"BaseType"}) {
9918 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9919 }
9920 if(defined $Info->{"TParam"})
9921 {
9922 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9923 {
9924 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9925 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9926 next;
9927 }
9928 if($TName eq "_BoolType") {
9929 next;
9930 }
9931 if($TName=~/\Asizeof\(/) {
9932 next;
9933 }
9934 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9935 check_TypeInfo($Tid, $LibVersion);
9936 }
9937 else
9938 {
9939 if(defined $Debug) {
9940 printMsg("WARNING", "missed type $TName");
9941 }
9942 }
9943 }
9944 }
9945
9946 # symbols
9947 if(defined $Info->{"Param"})
9948 {
9949 foreach my $Pos (keys(%{$Info->{"Param"}}))
9950 {
9951 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9952 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9953 }
9954 }
9955 }
9956 if(defined $Info->{"Return"}) {
9957 check_TypeInfo($Info->{"Return"}, $LibVersion);
9958 }
9959 if(defined $Info->{"Class"}) {
9960 check_TypeInfo($Info->{"Class"}, $LibVersion);
9961 }
9962}
9963
9964sub check_TypeInfo($$)
9965{
9966 my ($Tid, $LibVersion) = @_;
9967
9968 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9969 return;
9970 }
9971 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9972
9973 if(defined $TypeInfo{$LibVersion}{$Tid})
9974 {
9975 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9976 printMsg("ERROR", "missed type name ($Tid)");
9977 }
9978 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9979 }
9980 else {
9981 printMsg("ERROR", "missed type id $Tid");
9982 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009983}
9984
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009985sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009986{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009987 my ($TypeId, $LibVersion) = @_;
9988 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009989 if($Type{"Type"} eq "Typedef")
9990 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009991 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009992 if($Base{"Type"}=~/Class|Struct/)
9993 {
9994 if($Type{"Name"} eq $Base{"Name"}) {
9995 return 1;
9996 }
9997 elsif($Type{"Name"}=~/::(\w+)\Z/)
9998 {
9999 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10000 { # QPointer<QWidget>::QPointer
10001 return 1;
10002 }
10003 }
10004 }
10005 }
10006 return 0;
10007}
10008
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010009sub addExtension($)
10010{
10011 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010012 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010013 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010014 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010015 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010016 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10017 $TName=~s/\A(struct|union|class|enum) //;
10018 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010019
10020 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10021 "Header" => "extended.h",
10022 "ShortName" => $Symbol,
10023 "MnglName" => $Symbol,
10024 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10025 );
10026
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010027 $ExtendedSymbols{$Symbol} = 1;
10028 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10029 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010030 }
10031 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010032 $ExtendedSymbols{"external_func_0"} = 1;
10033 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10034 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010035}
10036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010037sub findMethod($$$)
10038{
10039 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010040 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010041 {
10042 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10043 return $VirtMethodInClass;
10044 }
10045 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10046 return $VirtMethodInBaseClasses;
10047 }
10048 }
10049 return "";
10050}
10051
10052sub findMethod_Class($$$)
10053{
10054 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010055 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010056 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10057 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10058 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10059 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10060 { # search for interface with the same parameters suffix (overridden)
10061 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10062 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010063 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10064 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010065 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10066 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010067 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10068 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10069 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10070 return $Candidate;
10071 }
10072 }
10073 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010074 else
10075 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010076 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10077 return $Candidate;
10078 }
10079 }
10080 }
10081 }
10082 return "";
10083}
10084
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010085sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010086{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010087 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010088 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010089 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010090 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10091 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010092 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010093 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010094 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010095 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10096 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010097 { # pure virtual D2-destructors are marked as "virt" in the dump
10098 # virtual D2-destructors are NOT marked as "virt" in the dump
10099 # both destructors are not presented in the v-table
10100 next;
10101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010102 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010103 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010105 }
10106}
10107
10108sub registerOverriding($)
10109{
10110 my $LibVersion = $_[0];
10111 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010112 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010113 foreach my $ClassName (@Classes)
10114 {
10115 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10116 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010117 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10118 { # pure virtuals
10119 next;
10120 }
10121 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10122 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010123 {
10124 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10125 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10126 { # both overridden virtual methods
10127 # and implemented pure virtual methods
10128 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10129 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10130 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010132 }
10133 }
10134 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10135 delete($VirtualTable{$LibVersion}{$ClassName});
10136 }
10137 }
10138}
10139
10140sub setVirtFuncPositions($)
10141{
10142 my $LibVersion = $_[0];
10143 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10144 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010145 my ($Num, $Rel) = (1, 0);
10146
10147 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010148 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010149 if($UsedDump{$LibVersion}{"DWARF"}) {
10150 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10151 }
10152 else {
10153 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10154 }
10155 foreach my $VirtFunc (@Funcs)
10156 {
10157 if($UsedDump{$LibVersion}{"DWARF"}) {
10158 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10159 }
10160 else {
10161 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10162 }
10163
10164 # set relative positions
10165 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10166 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10167 { # relative position excluding added and removed virtual functions
10168 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10169 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10170 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010174 }
10175 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010176 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010177 {
10178 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010179 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010180 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010181 }
10182 }
10183}
10184
10185sub get_sub_classes($$$)
10186{
10187 my ($ClassId, $LibVersion, $Recursive) = @_;
10188 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10189 my @Subs = ();
10190 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10191 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010192 if($Recursive)
10193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010194 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10195 push(@Subs, $SubSubId);
10196 }
10197 }
10198 push(@Subs, $SubId);
10199 }
10200 return @Subs;
10201}
10202
10203sub get_base_classes($$$)
10204{
10205 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010206 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207 return () if(not defined $ClassType{"Base"});
10208 my @Bases = ();
10209 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10210 keys(%{$ClassType{"Base"}}))
10211 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010212 if($Recursive)
10213 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010214 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10215 push(@Bases, $SubBaseId);
10216 }
10217 }
10218 push(@Bases, $BaseId);
10219 }
10220 return @Bases;
10221}
10222
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010223sub getVTable_Model($$)
10224{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010225 my ($ClassId, $LibVersion) = @_;
10226 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10227 my @Elements = ();
10228 foreach my $BaseId (@Bases, $ClassId)
10229 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010230 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010231 {
10232 if(defined $VirtualTable{$LibVersion}{$BName})
10233 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010234 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10235 if($UsedDump{$LibVersion}{"DWARF"}) {
10236 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10237 }
10238 else {
10239 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10240 }
10241 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010242 push(@Elements, $VFunc);
10243 }
10244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010245 }
10246 }
10247 return @Elements;
10248}
10249
10250sub getVShift($$)
10251{
10252 my ($ClassId, $LibVersion) = @_;
10253 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10254 my $VShift = 0;
10255 foreach my $BaseId (@Bases)
10256 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010257 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010258 {
10259 if(defined $VirtualTable{$LibVersion}{$BName}) {
10260 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010262 }
10263 }
10264 return $VShift;
10265}
10266
10267sub getShift($$)
10268{
10269 my ($ClassId, $LibVersion) = @_;
10270 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10271 my $Shift = 0;
10272 foreach my $BaseId (@Bases)
10273 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010274 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010275 {
10276 if($Size!=1)
10277 { # not empty base class
10278 $Shift+=$Size;
10279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010280 }
10281 }
10282 return $Shift;
10283}
10284
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010285sub getVTable_Size($$)
10286{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010288 my $Size = 0;
10289 # three approaches
10290 if(not $Size)
10291 { # real size
10292 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10293 $Size = keys(%VTable);
10294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010295 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010296 if(not $Size)
10297 { # shared library symbol size
10298 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10299 $Size /= $WORD_SIZE{$LibVersion};
10300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010301 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010302 if(not $Size)
10303 { # model size
10304 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10305 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10306 }
10307 }
10308 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010309}
10310
10311sub isCopyingClass($$)
10312{
10313 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010314 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010315}
10316
10317sub isLeafClass($$)
10318{
10319 my ($ClassId, $LibVersion) = @_;
10320 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10321}
10322
10323sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010324{ # check structured type for public fields
10325 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010326}
10327
10328sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010329{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010330 my ($TypePtr, $Skip, $Start, $End) = @_;
10331 return 0 if(not $TypePtr);
10332 if($End==-1) {
10333 $End = keys(%{$TypePtr->{"Memb"}})-1;
10334 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010335 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010336 {
10337 if($Skip and $Skip->{$MemPos})
10338 { # skip removed/added fields
10339 next;
10340 }
10341 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10342 {
10343 if(isPublic($TypePtr, $MemPos)) {
10344 return ($MemPos+1);
10345 }
10346 }
10347 }
10348 return 0;
10349}
10350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010351sub isReserved($)
10352{ # reserved fields == private
10353 my $MName = $_[0];
10354 if($MName=~/reserved|padding|f_spare/i) {
10355 return 1;
10356 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010357 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010358 return 1;
10359 }
10360 if($MName=~/(pad\d+)/i) {
10361 return 1;
10362 }
10363 return 0;
10364}
10365
10366sub isPublic($$)
10367{
10368 my ($TypePtr, $FieldPos) = @_;
10369 return 0 if(not $TypePtr);
10370 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10371 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10372 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10373 { # by name in C language
10374 # FIXME: add other methods to detect private members
10375 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10376 if($MName=~/priv|abidata|parent_object/i)
10377 { # C-styled private data
10378 return 0;
10379 }
10380 if(lc($MName) eq "abi")
10381 { # ABI information/reserved field
10382 return 0;
10383 }
10384 if(isReserved($MName))
10385 { # reserved fields
10386 return 0;
10387 }
10388 return 1;
10389 }
10390 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10391 { # by access in C++ language
10392 return 1;
10393 }
10394 return 0;
10395}
10396
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010397sub getVTable_Real($$)
10398{
10399 my ($ClassName, $LibVersion) = @_;
10400 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010402 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010403 if(defined $Type{"VTable"}) {
10404 return %{$Type{"VTable"}};
10405 }
10406 }
10407 return ();
10408}
10409
10410sub cmpVTables($)
10411{
10412 my $ClassName = $_[0];
10413 my $Res = cmpVTables_Real($ClassName, 1);
10414 if($Res==-1) {
10415 $Res = cmpVTables_Model($ClassName);
10416 }
10417 return $Res;
10418}
10419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010420sub cmpVTables_Model($)
10421{
10422 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010423 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010424 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010425 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 return 1;
10427 }
10428 }
10429 return 0;
10430}
10431
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010432sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010433{
10434 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010435 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10436 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010438 my %VTable_Old = getVTable_Real($ClassName, 1);
10439 my %VTable_New = getVTable_Real($ClassName, 2);
10440 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010441 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010442 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010444 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010445 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10446 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010447 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010449 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010451 my $Entry1 = $VTable_Old{$Offset};
10452 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010454 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010455 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010456 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010457
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458 $Entry1 = simpleVEntry($Entry1);
10459 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010460
10461 if($Entry1=~/ 0x/ and $Entry2=~/ 0x/)
10462 { # NOTE: problem with vtable-dumper
10463 next;
10464 }
10465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010466 if($Entry1 ne $Entry2)
10467 { # register as changed
10468 if($Entry1=~/::([^:]+)\Z/)
10469 {
10470 my $M1 = $1;
10471 if($Entry2=~/::([^:]+)\Z/)
10472 {
10473 my $M2 = $1;
10474 if($M1 eq $M2)
10475 { # overridden
10476 next;
10477 }
10478 }
10479 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010480 if(differentDumps("G"))
10481 {
10482 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10483 {
10484 # GCC 4.6.1: -0x00000000000000010
10485 # GCC 4.7.0: -16
10486 next;
10487 }
10488 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010489 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010490 }
10491 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010492 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493}
10494
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010495sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010497 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010498 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10499 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010500 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010501 { # already registered
10502 next;
10503 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010506 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010507 foreach my $Symbol (@Affected)
10508 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010509 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010511 "Target"=>$ClassName);
10512 }
10513 }
10514 }
10515}
10516
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010517sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010519 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010522 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010523 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010524 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010525 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010527 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 if($TName_Tid{1}{$ClassName}
10529 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010530 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010531 if(defined $CompleteSignature{1}{$Symbol}
10532 and $CompleteSignature{1}{$Symbol}{"Virt"})
10533 { # override some method in v.1
10534 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010535 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010536 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010537 }
10538 }
10539 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010540 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010541 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010542 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010543 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 if($TName_Tid{2}{$ClassName}
10545 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010546 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010547 if(defined $CompleteSignature{2}{$Symbol}
10548 and $CompleteSignature{2}{$Symbol}{"Virt"})
10549 { # override some method in v.2
10550 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010551 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553 }
10554 }
10555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010556 if($Level eq "Binary")
10557 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010558 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010559 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10560 { # check replacements, including pure virtual methods
10561 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10562 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010563 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010564 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10565 if($AddedPos==$RemovedPos)
10566 {
10567 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10568 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10569 last; # other methods will be reported as "added" or "removed"
10570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010572 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10573 {
10574 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10575 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 next;
10577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010578 my $ProblemType = "Virtual_Replacement";
10579 my @Affected = ($RemovedVFunc);
10580 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10581 { # pure methods
10582 if(not isUsedClass($ClassId, 1, $Level))
10583 { # not a parameter of some exported method
10584 next;
10585 }
10586 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010587
10588 # affected all methods (both virtual and non-virtual ones)
10589 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10590 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010592 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010593 foreach my $AffectedInt (@Affected)
10594 {
10595 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10596 { # affected exported methods only
10597 next;
10598 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010599 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10600 next;
10601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010602 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10603 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010604 "Target"=>get_Signature($AddedVFunc, 2),
10605 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010607 }
10608 }
10609 }
10610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010611 if(not checkDump(1, "2.0")
10612 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010613 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010614 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 return;
10616 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010617 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010619 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010620 next if(not $ClassId_Old);
10621 if(not isCreatable($ClassId_Old, 1))
10622 { # skip classes without public constructors (including auto-generated)
10623 # example: class has only a private exported or private inline constructor
10624 next;
10625 }
10626 if($ClassName=~/>/)
10627 { # skip affected template instances
10628 next;
10629 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010630 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010631 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010632 if(not $ClassId_New) {
10633 next;
10634 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010635 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010636 if($Class_New{"Type"}!~/Class|Struct/)
10637 { # became typedef
10638 if($Level eq "Binary") {
10639 next;
10640 }
10641 if($Level eq "Source")
10642 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010643 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010644 if($Class_New{"Type"}!~/Class|Struct/) {
10645 next;
10646 }
10647 $ClassId_New = $Class_New{"Tid"};
10648 }
10649 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010650
10651 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10652 { # incomplete info in the ABI dump
10653 next;
10654 }
10655
10656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010657 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10658 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 +040010659
10660 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10661 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10662
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010664 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10665 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010666 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10667 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010668 my $Shift_Old = getShift($ClassId_Old, 1);
10669 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010670 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 my ($Added, $Removed) = (0, 0);
10672 my @StableBases_Old = ();
10673 foreach my $BaseId (@Bases_Old)
10674 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010675 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010676 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010677 push(@StableBases_Old, $BaseId);
10678 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010679 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010680 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681 { # removed base
10682 # excluding namespace::SomeClass to SomeClass renaming
10683 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010684 if($Level eq "Binary")
10685 { # Binary-level
10686 if($Shift_Old ne $Shift_New)
10687 { # affected fields
10688 if(havePubFields(\%Class_Old)) {
10689 $ProblemKind .= "_And_Shift";
10690 }
10691 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10692 $ProblemKind .= "_And_Size";
10693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010694 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010695 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10696 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010697 { # affected v-table
10698 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010699 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010700 }
10701 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010702 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010703 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10704 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010705 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10706 {
10707 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10708 if($ProblemKind=~/VTable/) {
10709 $VTableChanged_M{$SubName}=1;
10710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010711 }
10712 }
10713 foreach my $Interface (@Affected)
10714 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010715 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10716 next;
10717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010718 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010719 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010720 "Target"=>$BaseName,
10721 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10722 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10723 "Shift"=>abs($Shift_New-$Shift_Old) );
10724 }
10725 $Removed+=1;
10726 }
10727 }
10728 my @StableBases_New = ();
10729 foreach my $BaseId (@Bases_New)
10730 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010731 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010732 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010733 push(@StableBases_New, $BaseId);
10734 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010735 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010736 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010737 { # added base
10738 # excluding namespace::SomeClass to SomeClass renaming
10739 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010740 if($Level eq "Binary")
10741 { # Binary-level
10742 if($Shift_Old ne $Shift_New)
10743 { # affected fields
10744 if(havePubFields(\%Class_Old)) {
10745 $ProblemKind .= "_And_Shift";
10746 }
10747 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10748 $ProblemKind .= "_And_Size";
10749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010750 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010751 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10752 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 { # affected v-table
10754 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010755 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010756 }
10757 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010758 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10760 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010761 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10762 {
10763 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10764 if($ProblemKind=~/VTable/) {
10765 $VTableChanged_M{$SubName}=1;
10766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 }
10768 }
10769 foreach my $Interface (@Affected)
10770 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010771 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10772 next;
10773 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010774 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010775 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010776 "Target"=>$BaseName,
10777 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10778 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10779 "Shift"=>abs($Shift_New-$Shift_Old) );
10780 }
10781 $Added+=1;
10782 }
10783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010784 if($Level eq "Binary")
10785 { # Binary-level
10786 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010787 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10788 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010789 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010790 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010791 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010792 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010793 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010794 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10795 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010796 if($NewPos!=$OldPos)
10797 { # changed position of the base class
10798 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010799 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010800 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10801 next;
10802 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010803 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10804 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010805 "Target"=>$BaseName,
10806 "Old_Value"=>$OldPos-1,
10807 "New_Value"=>$NewPos-1 );
10808 }
10809 }
10810 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10811 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10812 { # became non-virtual base
10813 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10814 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010815 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10816 next;
10817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010818 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10819 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010820 "Target"=>$BaseName );
10821 }
10822 }
10823 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10824 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10825 { # became virtual base
10826 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10827 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010828 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10829 next;
10830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010831 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10832 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010833 "Target"=>$BaseName );
10834 }
10835 }
10836 }
10837 }
10838 # detect size changes in base classes
10839 if($Shift_Old!=$Shift_New)
10840 { # size of allocable class
10841 foreach my $BaseId (@StableBases_Old)
10842 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010843 my %BaseType = get_Type($BaseId, 1);
10844 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010845 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010846 if($Size_Old ne $Size_New
10847 and $Size_Old and $Size_New)
10848 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010849 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010850 if(isCopyingClass($BaseId, 1)) {
10851 $ProblemType = "Size_Of_Copying_Class";
10852 }
10853 elsif($AllocableClass{1}{$BaseType{"Name"}})
10854 {
10855 if($Size_New>$Size_Old)
10856 { # increased size
10857 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010859 else
10860 { # decreased size
10861 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10862 if(not havePubFields(\%Class_Old))
10863 { # affected class has no public members
10864 next;
10865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010867 }
10868 next if(not $ProblemType);
10869 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10870 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010871 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10872 next;
10873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10875 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010876 "Target"=>$BaseType{"Name"},
10877 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10878 "New_Size"=>$Size_New*$BYTE_SIZE );
10879 }
10880 }
10881 }
10882 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010883 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010884 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010885 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010886 { # compare virtual tables size in base classes
10887 my $VShift_Old = getVShift($ClassId_Old, 1);
10888 my $VShift_New = getVShift($ClassId_New, 2);
10889 if($VShift_Old ne $VShift_New)
10890 { # changes in the base class or changes in the list of base classes
10891 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10892 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10893 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010894 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010895 foreach my $BaseId (@AllBases_Old)
10896 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010897 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010898 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010899 { # lost base
10900 next;
10901 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010902 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10903 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010904 if($VSize_Old!=$VSize_New)
10905 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010906 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010907 { # TODO: affected non-virtual methods?
10908 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10910 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010911 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010912 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010913 { # skip interfaces that have not changed the absolute virtual position
10914 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010916 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10917 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010918 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010919 $VTableChanged_M{$BaseType{"Name"}} = 1;
10920 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010921 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10922 { # the reason of the layout change: added virtual functions
10923 next if($VirtualReplacement{$VirtFunc});
10924 my $ProblemType = "Added_Virtual_Method";
10925 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10926 $ProblemType = "Added_Pure_Virtual_Method";
10927 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010928 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010929 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 "Target"=>get_Signature($VirtFunc, 2) );
10931 }
10932 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10933 { # the reason of the layout change: removed virtual functions
10934 next if($VirtualReplacement{$VirtFunc});
10935 my $ProblemType = "Removed_Virtual_Method";
10936 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10937 $ProblemType = "Removed_Pure_Virtual_Method";
10938 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010939 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 "Target"=>get_Signature($VirtFunc, 1) );
10942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010943 }
10944 }
10945 }
10946 }
10947 }
10948 }
10949 }
10950}
10951
10952sub isCreatable($$)
10953{
10954 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010955 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010956 or isCopyingClass($ClassId, $LibVersion)) {
10957 return 1;
10958 }
10959 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10960 { # Fix for incomplete data: if this class has
10961 # a base class then it should also has a constructor
10962 return 1;
10963 }
10964 if($ReturnedClass{$LibVersion}{$ClassId})
10965 { # returned by some method of this class
10966 # or any other class
10967 return 1;
10968 }
10969 return 0;
10970}
10971
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010972sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010973{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010975 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10976 { # parameter of some exported method
10977 return 1;
10978 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010979 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10980 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010981 { # method from target class
10982 return 1;
10983 }
10984 return 0;
10985}
10986
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010988{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010990 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010991 # - virtual
10992 # - pure-virtual
10993 # - non-virtual
10994 if($CompleteSignature{1}{$Interface}{"Data"})
10995 { # global data is not affected
10996 return;
10997 }
10998 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010999 if(not $Class_Id) {
11000 return;
11001 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011002 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011003 if(cmpVTables_Real($CName, 1)==0)
11004 { # no changes
11005 return;
11006 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 $CheckedTypes{$Level}{$CName} = 1;
11008 if($Level eq "Binary")
11009 { # Binary-level
11010 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11011 and not isUsedClass($Class_Id, 1, $Level))
11012 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011013 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011014 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011015 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011016 }
11017 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11018 {
11019 if(defined $VirtualTable{2}{$CName}{$Func}
11020 and defined $CompleteSignature{2}{$Func})
11021 {
11022 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11023 and $CompleteSignature{2}{$Func}{"PureVirt"})
11024 { # became pure virtual
11025 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11026 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011027 "Target"=>get_Signature_M($Func, 1) );
11028 $VTableChanged_M{$CName} = 1;
11029 }
11030 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11031 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11032 { # became non-pure virtual
11033 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11034 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011035 "Target"=>get_Signature_M($Func, 1) );
11036 $VTableChanged_M{$CName} = 1;
11037 }
11038 }
11039 }
11040 if($Level eq "Binary")
11041 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 # check virtual table structure
11043 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11044 {
11045 next if($Interface eq $AddedVFunc);
11046 next if($VirtualReplacement{$AddedVFunc});
11047 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11048 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11049 { # pure virtual methods affect all others (virtual and non-virtual)
11050 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011051 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011052 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011053 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011054 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011055 elsif(not defined $VirtualTable{1}{$CName}
11056 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011059 { # became polymorphous class, added v-table pointer
11060 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011061 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011062 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011063 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011064 }
11065 else
11066 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011067 my $VSize_Old = getVTable_Size($CName, 1);
11068 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011069 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011070 if(isCopyingClass($Class_Id, 1))
11071 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11072 my $ProblemType = "Added_Virtual_Method";
11073 if(isLeafClass($Class_Id, 1)) {
11074 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11075 }
11076 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11077 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011078 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011079 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011080 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011081 else
11082 {
11083 my $ProblemType = "Added_Virtual_Method";
11084 if(isLeafClass($Class_Id, 1)) {
11085 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11086 }
11087 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11088 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011090 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011092 }
11093 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011094 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11095 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011096 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011097 if(defined $VirtualTable{1}{$CName}
11098 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011100 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11101 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011102
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011103 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011104 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011105 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11106 foreach my $ASymbol (@Affected)
11107 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011108 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11109 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011110 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011111 next;
11112 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011113 }
11114 $CheckedSymbols{$Level}{$ASymbol} = 1;
11115 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11116 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011117 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011118 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 }
11122 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011123 else {
11124 # safe
11125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011127 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11128 {
11129 next if($VirtualReplacement{$RemovedVFunc});
11130 if($RemovedVFunc eq $Interface
11131 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11132 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011133 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011134 next;
11135 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011136 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 { # became non-polymorphous class, removed v-table pointer
11138 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11139 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011140 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011141 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011142 }
11143 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11144 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11145 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011146 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011147 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011148 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11149 next;
11150 }
11151 my $VPos_New = -1;
11152 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011153 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011154 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11155 }
11156 else
11157 {
11158 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011159 next;
11160 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011161 }
11162 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11163 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11164 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11165 {
11166 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11167 foreach my $ASymbol (@Affected)
11168 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011169 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11170 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011171 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011172 next;
11173 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011174 }
11175 my $ProblemType = "Removed_Virtual_Method";
11176 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11177 $ProblemType = "Removed_Pure_Virtual_Method";
11178 }
11179 $CheckedSymbols{$Level}{$ASymbol} = 1;
11180 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11181 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011182 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011183 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011185 }
11186 }
11187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011188 }
11189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011190 else
11191 { # Source-level
11192 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011193 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 next if($Interface eq $AddedVFunc);
11195 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011196 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11198 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011199 "Target"=>get_Signature($AddedVFunc, 2) );
11200 }
11201 }
11202 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11203 {
11204 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11205 {
11206 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11207 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011208 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011209 }
11210 }
11211 }
11212}
11213
11214sub find_MemberPair_Pos_byName($$)
11215{
11216 my ($Member_Name, $Pair_Type) = @_;
11217 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11218 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11219 {
11220 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11221 {
11222 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11223 $Name=~s/\A[_]+|[_]+\Z//g;
11224 if($Name eq $Member_Name) {
11225 return $MemberPair_Pos;
11226 }
11227 }
11228 }
11229 return "lost";
11230}
11231
11232sub find_MemberPair_Pos_byVal($$)
11233{
11234 my ($Member_Value, $Pair_Type) = @_;
11235 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11236 {
11237 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11238 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11239 return $MemberPair_Pos;
11240 }
11241 }
11242 return "lost";
11243}
11244
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011245sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011246{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011247 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011248 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011249 if( $_->{"T1"} eq $_[0]
11250 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011251 {
11252 return 1;
11253 }
11254 }
11255 return 0;
11256}
11257
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011258sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011259{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011260 my %IDs = (
11261 "T1" => $_[0],
11262 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011263 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011264 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011265}
11266
11267sub isRenamed($$$$$)
11268{
11269 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11270 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11271 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011272 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011273 if(not defined $Type2->{"Memb"}{$MemPos}) {
11274 return "";
11275 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011276 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011277 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011278
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011279 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11280 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011281 if($MemberPair_Pos_Rev eq "lost")
11282 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011283 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11284 { # base type match
11285 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011286 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011287 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11288 { # exact type match
11289 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011290 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011291 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11292 { # size match
11293 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011295 if(isReserved($Pair_Name))
11296 { # reserved fields
11297 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011298 }
11299 }
11300 return "";
11301}
11302
11303sub isLastElem($$)
11304{
11305 my ($Pos, $TypeRef) = @_;
11306 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11307 if($Name=~/last|count|max|total/i)
11308 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11309 return 1;
11310 }
11311 elsif($Name=~/END|NLIMITS\Z/)
11312 { # __RLIMIT_NLIMITS
11313 return 1;
11314 }
11315 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11316 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11317 { # NImageFormats, NColorRoles
11318 return 1;
11319 }
11320 return 0;
11321}
11322
11323sub nonComparable($$)
11324{
11325 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011326
11327 my $N1 = $T1->{"Name"};
11328 my $N2 = $T2->{"Name"};
11329
11330 $N1=~s/\A(struct|union|enum) //;
11331 $N2=~s/\A(struct|union|enum) //;
11332
11333 if($N1 ne $N2
11334 and not isAnon($N1)
11335 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011336 { # different names
11337 if($T1->{"Type"} ne "Pointer"
11338 or $T2->{"Type"} ne "Pointer")
11339 { # compare base types
11340 return 1;
11341 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011342 if($N1!~/\Avoid\s*\*/
11343 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 {
11345 return 1;
11346 }
11347 }
11348 elsif($T1->{"Type"} ne $T2->{"Type"})
11349 { # different types
11350 if($T1->{"Type"} eq "Class"
11351 and $T2->{"Type"} eq "Struct")
11352 { # "class" to "struct"
11353 return 0;
11354 }
11355 elsif($T2->{"Type"} eq "Class"
11356 and $T1->{"Type"} eq "Struct")
11357 { # "struct" to "class"
11358 return 0;
11359 }
11360 else
11361 { # "class" to "enum"
11362 # "union" to "class"
11363 # ...
11364 return 1;
11365 }
11366 }
11367 return 0;
11368}
11369
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011370sub isOpaque($)
11371{
11372 my $T = $_[0];
11373 if(not defined $T->{"Memb"})
11374 {
11375 return 1;
11376 }
11377 return 0;
11378}
11379
11380sub removeVPtr($)
11381{ # support for old ABI dumps
11382 my $TPtr = $_[0];
11383 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11384 if($#Pos>=1)
11385 {
11386 foreach my $Pos (0 .. $#Pos-1)
11387 {
11388 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11389 }
11390 delete($TPtr->{"Memb"}{$#Pos});
11391 }
11392}
11393
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011394sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011395{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011396 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011397 return {} if(not $Type1_Id or not $Type2_Id);
11398
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011399 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011400 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011401 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011403
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011404 my %Type1 = get_Type($Type1_Id, 1);
11405 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011406 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011407 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011409
11410 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011411 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11412 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011413
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011414 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11415
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011416 my %SubProblems = ();
11417
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011418 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11419 {
11420 if($Type1_Pure{"Type"}=~/Struct|Union/
11421 and $Type2_Pure{"Type"}=~/Struct|Union/)
11422 {
11423 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11424 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011425 if(not defined $UsedDump{1}{"DWARF"}
11426 and not defined $UsedDump{2}{"DWARF"})
11427 {
11428 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11429 "Target"=>$Type1_Pure{"Name"},
11430 "Type_Name"=>$Type1_Pure{"Name"} );
11431 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011432
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011433 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011434 }
11435 }
11436 }
11437
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011438 if(not $Type1_Pure{"Size"}
11439 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011440 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011441 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11442 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11443 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011444 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011445 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011446 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011447 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011448 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011449 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011450 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011451 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11452 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11453 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011454
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011455 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11456 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011457 }
11458
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011459 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11460 { # support for old ABI dumps
11461 # _vptr field added in 3.0
11462 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11463 {
11464 if(defined $Type2_Pure{"Memb"}
11465 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11466 {
11467 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11468 delete($Type2_Pure{"Memb"}{0});
11469 }
11470 else {
11471 removeVPtr(\%Type2_Pure);
11472 }
11473 }
11474 }
11475 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11476 {
11477 if(defined $Type1_Pure{"Memb"}
11478 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11479 {
11480 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11481 delete($Type1_Pure{"Memb"}{0});
11482 }
11483 else {
11484 removeVPtr(\%Type1_Pure);
11485 }
11486 }
11487 }
11488 }
11489
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011490 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11491 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011492
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011493 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011494 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11495 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011496 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011497 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11498 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011499 if($Base_1{"Name"} ne $Base_2{"Name"})
11500 {
11501 if(differentDumps("G")
11502 or differentDumps("V"))
11503 { # different GCC versions or different dumps
11504 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11505 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11506 # std::__va_list and __va_list
11507 $Base_1{"Name"}=~s/\A(\w+::)+//;
11508 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011509 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11510 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011512 }
11513 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11514 and $Base_1{"Name"} ne $Base_2{"Name"})
11515 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011516 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011517 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011518 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011519 {
11520 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11521 "Target"=>$Typedef_1{"Name"},
11522 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011523 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11524 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11525 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011526 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11527 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011528 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011529 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011530 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11531 {
11532 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11533 "Target"=>$Typedef_1{"Name"},
11534 "Type_Name"=>$Typedef_1{"Name"},
11535 "Old_Value"=>$Base_1{"Name"},
11536 "New_Value"=>$Base_2{"Name"} );
11537 }
11538 else
11539 {
11540 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11541 "Target"=>$Typedef_1{"Name"},
11542 "Type_Name"=>$Typedef_1{"Name"},
11543 "Old_Value"=>$Base_1{"Name"},
11544 "New_Value"=>$Base_2{"Name"} );
11545 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011547 }
11548 }
11549 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11550 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011551 my $TT1 = $Type1_Pure{"Type"};
11552 my $TT2 = $Type2_Pure{"Type"};
11553
11554 if($TT1 ne $TT2
11555 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011556 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011557 my $Short1 = $Type1_Pure{"Name"};
11558 my $Short2 = $Type2_Pure{"Name"};
11559
11560 $Short1=~s/\A\Q$TT1\E //ig;
11561 $Short2=~s/\A\Q$TT2\E //ig;
11562
11563 if($Short1 eq $Short2)
11564 {
11565 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11566 "Target"=>$Type1_Pure{"Name"},
11567 "Type_Name"=>$Type1_Pure{"Name"},
11568 "Old_Value"=>lc($Type1_Pure{"Type"}),
11569 "New_Value"=>lc($Type2_Pure{"Type"}) );
11570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011571 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011572 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011574 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011575 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11576 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11577 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11578 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011579 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011580 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011581 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011582 {
11583 my $ProblemKind = "DataType_Size";
11584 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011585 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011586 {
11587 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11588 $ProblemKind = "Size_Of_Copying_Class";
11589 }
11590 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11591 {
11592 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11593 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11594 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011595 else
11596 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011597 # descreased size of allocable class
11598 # it has no special effects
11599 }
11600 }
11601 }
11602 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11603 "Target"=>$Type1_Pure{"Name"},
11604 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011605 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011606 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011607 }
11608 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011609 if(defined $Type1_Pure{"BaseType"}
11610 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011611 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011612 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11613 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011614 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011615 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11616 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011617 }
11618 }
11619 }
11620 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11621 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11622 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11623 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11624 { # detect removed and renamed fields
11625 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11626 next if(not $Member_Name);
11627 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);
11628 if($MemberPair_Pos eq "lost")
11629 {
11630 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11631 {
11632 if(isUnnamed($Member_Name))
11633 { # support for old-version dumps
11634 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011635 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 next;
11637 }
11638 }
11639 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11640 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011641 $RenamedField{$Member_Pos} = $RenamedTo;
11642 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011643 }
11644 else
11645 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011646 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011647 }
11648 }
11649 elsif($Type1_Pure{"Type"} eq "Enum")
11650 {
11651 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11652 next if($Member_Value1 eq "");
11653 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11654 if($MemberPair_Pos ne "lost")
11655 { # renamed
11656 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11657 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11658 if($MemberPair_Pos_Rev eq "lost")
11659 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011660 $RenamedField{$Member_Pos} = $RenamedTo;
11661 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011662 }
11663 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011664 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 }
11666 }
11667 else
11668 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011669 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011670 }
11671 }
11672 }
11673 else
11674 { # related
11675 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11676 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11677 }
11678 }
11679 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11680 { # detect added fields
11681 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11682 next if(not $Member_Name);
11683 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);
11684 if($MemberPair_Pos eq "lost")
11685 {
11686 if(isUnnamed($Member_Name))
11687 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011688 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011689 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011690 next;
11691 }
11692 }
11693 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11694 {
11695 if(not $RenamedField_Rev{$Member_Pos})
11696 { # added
11697 $AddedField{$Member_Pos}=1;
11698 }
11699 }
11700 }
11701 }
11702 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11703 { # detect moved fields
11704 my (%RelPos, %RelPosName, %AbsPos) = ();
11705 my $Pos = 0;
11706 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11707 { # relative positions in 1st version
11708 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11709 next if(not $Member_Name);
11710 if(not $RemovedField{$Member_Pos})
11711 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011712 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011713 $RelPosName{1}{$Pos} = $Member_Name;
11714 $AbsPos{1}{$Pos++} = $Member_Pos;
11715 }
11716 }
11717 $Pos = 0;
11718 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11719 { # relative positions in 2nd version
11720 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11721 next if(not $Member_Name);
11722 if(not $AddedField{$Member_Pos})
11723 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011724 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011725 $RelPosName{2}{$Pos} = $Member_Name;
11726 $AbsPos{2}{$Pos++} = $Member_Pos;
11727 }
11728 }
11729 foreach my $Member_Name (keys(%{$RelPos{1}}))
11730 {
11731 my $RPos1 = $RelPos{1}{$Member_Name};
11732 my $AbsPos1 = $NameToPosA{$Member_Name};
11733 my $Member_Name2 = $Member_Name;
11734 if(my $RenamedTo = $RenamedField{$AbsPos1})
11735 { # renamed
11736 $Member_Name2 = $RenamedTo;
11737 }
11738 my $RPos2 = $RelPos{2}{$Member_Name2};
11739 if($RPos2 ne "" and $RPos1 ne $RPos2)
11740 { # different relative positions
11741 my $AbsPos2 = $NameToPosB{$Member_Name2};
11742 if($AbsPos1 ne $AbsPos2)
11743 { # different absolute positions
11744 my $ProblemType = "Moved_Field";
11745 if(not isPublic(\%Type1_Pure, $AbsPos1))
11746 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011747 if($Level eq "Source") {
11748 next;
11749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011750 $ProblemType = "Moved_Private_Field";
11751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011752 if($Level eq "Binary"
11753 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011755 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011756 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011757 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011758 if($MemSize1 ne $MemSize2) {
11759 $ProblemType .= "_And_Size";
11760 }
11761 }
11762 if($ProblemType eq "Moved_Private_Field") {
11763 next;
11764 }
11765 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11766 "Target"=>$Member_Name,
11767 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011768 "Old_Value"=>$RPos1,
11769 "New_Value"=>$RPos2 );
11770 }
11771 }
11772 }
11773 }
11774 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011775 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011776 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11777 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011778 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 if(my $RenamedTo = $RenamedField{$Member_Pos})
11780 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011781 if(defined $Constants{2}{$Member_Name})
11782 {
11783 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11784 { # define OLD NEW
11785 next; # Safe
11786 }
11787 }
11788
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011789 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11790 {
11791 if(isPublic(\%Type1_Pure, $Member_Pos))
11792 {
11793 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11794 "Target"=>$Member_Name,
11795 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011796 "Old_Value"=>$Member_Name,
11797 "New_Value"=>$RenamedTo );
11798 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011799 elsif(isReserved($Member_Name))
11800 {
11801 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11802 "Target"=>$Member_Name,
11803 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011804 "Old_Value"=>$Member_Name,
11805 "New_Value"=>$RenamedTo );
11806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011807 }
11808 elsif($Type1_Pure{"Type"} eq "Enum")
11809 {
11810 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11811 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11812 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011813 "Old_Value"=>$Member_Name,
11814 "New_Value"=>$RenamedTo );
11815 }
11816 }
11817 elsif($RemovedField{$Member_Pos})
11818 { # removed
11819 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11820 {
11821 my $ProblemType = "Removed_Field";
11822 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011823 or isUnnamed($Member_Name))
11824 {
11825 if($Level eq "Source") {
11826 next;
11827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011828 $ProblemType = "Removed_Private_Field";
11829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011830 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011831 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011832 {
11833 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11834 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011835 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 +040011836 { # changed offset
11837 $ProblemType .= "_And_Layout";
11838 }
11839 }
11840 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11841 { # affected size
11842 $ProblemType .= "_And_Size";
11843 }
11844 }
11845 if($ProblemType eq "Removed_Private_Field") {
11846 next;
11847 }
11848 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11849 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011850 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 }
11852 elsif($Type2_Pure{"Type"} eq "Union")
11853 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011854 if($Level eq "Binary"
11855 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011856 {
11857 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11858 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011859 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011860 }
11861 else
11862 {
11863 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11864 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011865 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011866 }
11867 }
11868 elsif($Type1_Pure{"Type"} eq "Enum")
11869 {
11870 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11871 "Target"=>$Member_Name,
11872 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011873 "Old_Value"=>$Member_Name );
11874 }
11875 }
11876 else
11877 { # changed
11878 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11879 if($Type1_Pure{"Type"} eq "Enum")
11880 {
11881 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11882 next if($Member_Value1 eq "");
11883 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11884 next if($Member_Value2 eq "");
11885 if($Member_Value1 ne $Member_Value2)
11886 {
11887 my $ProblemType = "Enum_Member_Value";
11888 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11889 $ProblemType = "Enum_Last_Member_Value";
11890 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011891 if($SkipConstants{1}{$Member_Name}) {
11892 $ProblemType = "Enum_Private_Member_Value";
11893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011894 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11895 "Target"=>$Member_Name,
11896 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011897 "Old_Value"=>$Member_Value1,
11898 "New_Value"=>$Member_Value2 );
11899 }
11900 }
11901 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11902 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011903 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11904 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11905
11906 if($Access1 ne "private"
11907 and $Access2 eq "private")
11908 {
11909 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11910 "Target"=>$Member_Name,
11911 "Type_Name"=>$Type1_Pure{"Name"});
11912 }
11913 elsif($Access1 ne "protected"
11914 and $Access1 ne "private"
11915 and $Access2 eq "protected")
11916 {
11917 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11918 "Target"=>$Member_Name,
11919 "Type_Name"=>$Type1_Pure{"Name"});
11920 }
11921
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11923 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011924 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011925 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11926 $SizeV1 = $BSize1;
11927 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011928 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011929 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11930 $SizeV2 = $BSize2;
11931 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011932 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11933 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011934 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011935 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011936 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011937 {
11938 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11939 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11940 { # field size change (including anon-structures and unions)
11941 # - same types
11942 # - unnamed types
11943 # - bitfields
11944 my $ProblemType = "Field_Size";
11945 if(not isPublic(\%Type1_Pure, $Member_Pos)
11946 or isUnnamed($Member_Name))
11947 { # should not be accessed by applications, goes to "Low Severity"
11948 # example: "abidata" members in GStreamer types
11949 $ProblemType = "Private_".$ProblemType;
11950 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011951 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 +040011952 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011953 if($Type2_Pure{"Type"} ne "Union"
11954 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011956 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 +040011957 { # changed offset
11958 $ProblemType .= "_And_Layout";
11959 }
11960 }
11961 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11962 $ProblemType .= "_And_Type_Size";
11963 }
11964 }
11965 if($ProblemType eq "Private_Field_Size")
11966 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011967 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011968 if($ProblemType eq "Field_Size")
11969 {
11970 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11971 { # Low severity
11972 $ProblemType = "Struct_Field_Size_Increased";
11973 }
11974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011975 if($ProblemType)
11976 { # register a problem
11977 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11978 "Target"=>$Member_Name,
11979 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011980 "Old_Size"=>$SizeV1,
11981 "New_Size"=>$SizeV2);
11982 }
11983 }
11984 }
11985 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11986 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11987 { # do NOT check bitfield type changes
11988 next;
11989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011990 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011991 {
11992 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11993 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11994 {
11995 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11996 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011997 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011998 }
11999 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12000 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12001 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012002 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012003 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012004 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012005 }
12006 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012007 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12008 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012010 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12011 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012012
12013 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012014 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012015 or $ProblemType eq "Field_Type_And_Size"
12016 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012017 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012018 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012019 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012020 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012021 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012022 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012023 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012024 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012025 }
12026 }
12027 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12028 {
12029 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012030 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012031 }
12032 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012033 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012034 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012035 }
12036 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12037 {
12038 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012039 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012040 }
12041 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012042 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012043 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012044 }
12045 }
12046 }
12047
12048 if($Level eq "Source")
12049 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012050 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012051 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012052 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12053 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012054
12055 if($ProblemType eq "Field_Type")
12056 {
12057 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012058 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012059 }
12060 }
12061 }
12062 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012063
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012064 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012065 {
12066 my $ProblemType_Init = $ProblemType;
12067 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012068 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012069 if(not isPublic(\%Type1_Pure, $Member_Pos)
12070 or isUnnamed($Member_Name)) {
12071 $ProblemType = "Private_".$ProblemType;
12072 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012073 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 +040012074 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012075 if($Type2_Pure{"Type"} ne "Union"
12076 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012078 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 +040012079 { # changed offset
12080 $ProblemType .= "_And_Layout";
12081 }
12082 }
12083 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12084 $ProblemType .= "_And_Type_Size";
12085 }
12086 }
12087 }
12088 else
12089 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012090 # TODO: Private_Field_Type rule?
12091
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012092 if(not isPublic(\%Type1_Pure, $Member_Pos)
12093 or isUnnamed($Member_Name)) {
12094 next;
12095 }
12096 }
12097 if($ProblemType eq "Private_Field_Type_And_Size")
12098 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012099 }
12100 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12101 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012102 "Type_Name"=>$Type1_Pure{"Name"});
12103
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012104 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012105 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012106 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012107 }
12108 }
12109 if(not isPublic(\%Type1_Pure, $Member_Pos))
12110 { # do NOT check internal type changes
12111 next;
12112 }
12113 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012114 { # checking member type changes
12115 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12116
12117 my %DupProblems = ();
12118
12119 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012120 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012121 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012122 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012123 if(not defined $AllAffected)
12124 {
12125 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12126 next;
12127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012129
12130 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12131 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12132
12133 if(not defined $AllAffected)
12134 {
12135 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 }
12137 }
12138 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012139
12140 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012141 }
12142 }
12143 }
12144 }
12145 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12146 { # checking added members, public and private
12147 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12148 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012149 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012150 if($AddedField{$Member_Pos})
12151 { # added
12152 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12153 {
12154 my $ProblemType = "Added_Field";
12155 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012156 or isUnnamed($Member_Name))
12157 {
12158 if($Level eq "Source") {
12159 next;
12160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012161 $ProblemType = "Added_Private_Field";
12162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012163 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012164 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012165 {
12166 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12167 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012168 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 +040012169 { # changed offset
12170 $ProblemType .= "_And_Layout";
12171 }
12172 }
12173 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12174 $ProblemType .= "_And_Size";
12175 }
12176 }
12177 if($ProblemType eq "Added_Private_Field")
12178 { # skip added private fields
12179 next;
12180 }
12181 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12182 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012183 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 }
12185 elsif($Type2_Pure{"Type"} eq "Union")
12186 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012187 if($Level eq "Binary"
12188 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012189 {
12190 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12191 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012192 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012193 }
12194 else
12195 {
12196 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12197 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012198 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012199 }
12200 }
12201 elsif($Type2_Pure{"Type"} eq "Enum")
12202 {
12203 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12204 next if($Member_Value eq "");
12205 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12206 "Target"=>$Member_Name,
12207 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012208 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012209 }
12210 }
12211 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012212
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012214 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012215}
12216
12217sub isUnnamed($) {
12218 return $_[0]=~/\Aunnamed\d+\Z/;
12219}
12220
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012221sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012222{
12223 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012224 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12225 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12226 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012228 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012229 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012230 }
12231 return $TypeName;
12232}
12233
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012234sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012235{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012237 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012238 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12239 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012240 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012241 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12242 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012243 return () if(not $Type{"Type"});
12244 if($Type{"Type"} ne $Type_Type)
12245 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012246 return () if(not $Type{"BaseType"});
12247 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012249 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 return %Type;
12251}
12252
12253my %TypeSpecAttributes = (
12254 "Const" => 1,
12255 "Volatile" => 1,
12256 "ConstVolatile" => 1,
12257 "Restrict" => 1,
12258 "Typedef" => 1
12259);
12260
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012261sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012263 my ($TypeId, $Info) = @_;
12264 if(not $TypeId or not $Info
12265 or not $Info->{$TypeId}) {
12266 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012267 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012268 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12269 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12270 }
12271 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012272 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012273 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012274 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012276 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012277 return %Type;
12278}
12279
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012280sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012282 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012284 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12285 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012286 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012287 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12288 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012289 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12290 my $PLevel = 0;
12291 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12292 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012294 return $PLevel if(not $Type{"BaseType"});
12295 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12296 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12297 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298}
12299
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012300sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012301{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012302 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012304 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12305 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012307 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12308 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012309 return %Type if(not $Type{"BaseType"});
12310 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012311 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012312 return %Type;
12313}
12314
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012315sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012316{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012317 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012318 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012319 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12320 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012321 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012322 my $Qual = "";
12323 if($Type{"Type"} eq "Pointer") {
12324 $Qual .= "*";
12325 }
12326 elsif($Type{"Type"} eq "Ref") {
12327 $Qual .= "&";
12328 }
12329 elsif($Type{"Type"} eq "ConstVolatile") {
12330 $Qual .= "const volatile";
12331 }
12332 elsif($Type{"Type"} eq "Const"
12333 or $Type{"Type"} eq "Volatile"
12334 or $Type{"Type"} eq "Restrict") {
12335 $Qual .= lc($Type{"Type"});
12336 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012337 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 return $BQual.$Qual;
12339}
12340
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012341sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012342{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012343 my ($TypeId, $Info) = @_;
12344 if(not $TypeId or not $Info
12345 or not $Info->{$TypeId}) {
12346 return ();
12347 }
12348 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012349 return %Type if(not $Type{"BaseType"});
12350 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012351 {
12352 if($Info->{$BTid}) {
12353 return %{$Info->{$BTid}};
12354 }
12355 else { # something is going wrong
12356 return ();
12357 }
12358 }
12359 else {
12360 return %Type;
12361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012362}
12363
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012364sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012366 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012367 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012368 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12369 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012370}
12371
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012372sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012373{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012374 my $Symbol = $_[0];
12375 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12376}
12377
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012378sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012379 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12380}
12381
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012382sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012383{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012384 my ($SInfo, $LibVersion) = @_;
12385
12386 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012388 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012390 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012391 return 1;
12392 }
12393 }
12394 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012395 if(my $ShortName = $SInfo->{"ShortName"})
12396 {
12397 if(index($ShortName,"<")!=-1
12398 and index($ShortName,">")!=-1) {
12399 return 1;
12400 }
12401 }
12402
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012403 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012404}
12405
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012406sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012407{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012408 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012409 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012411 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012412 { # class specialization
12413 return 1;
12414 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012415 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012416 { # method specialization
12417 return 1;
12418 }
12419 }
12420 return 0;
12421}
12422
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012423sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012424{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012425 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012426
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012427 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012428 { # non-public global data
12429 return 0;
12430 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012431
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012432 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012433 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012434 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012435 }
12436
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012437 if($Symbol=~/\A_Z/)
12438 {
12439 if($Symbol=~/[CD][3-4]E/) {
12440 return 0;
12441 }
12442 }
12443
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012444 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012445 { # support for old ABI dumps in --headers-only mode
12446 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12447 {
12448 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12449 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012450 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 if(not $PType or $PType eq "Unknown") {
12452 return 0;
12453 }
12454 }
12455 }
12456 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012457 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012458 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012459 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461 if($SkipSymbols{$LibVersion}{$Symbol})
12462 { # user defined symbols to ignore
12463 return 0;
12464 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012465
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012466 if($SymbolsListPath and not $SymbolsList{$Symbol})
12467 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012468 if(not $TargetHeadersPath or not $Header
12469 or not is_target_header($Header, 1))
12470 { # -symbols-list | -headers-list
12471 return 0;
12472 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012473 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012474
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012475 if($AppPath and not $SymbolsList_App{$Symbol})
12476 { # user defined symbols (in application)
12477 return 0;
12478 }
12479
12480 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12481
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012482 if($ClassId)
12483 {
12484 if(not isTargetType($ClassId, $LibVersion)) {
12485 return 0;
12486 }
12487 }
12488
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012489 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12490 if(not $NameSpace and $ClassId)
12491 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012492 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012493 }
12494 if($NameSpace)
12495 { # user defined namespaces to ignore
12496 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12497 return 0;
12498 }
12499 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12500 { # nested namespaces
12501 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12502 return 0;
12503 }
12504 }
12505 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012506 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012507 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012508 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509 { # --skip-headers or <skip_headers> (not <skip_including>)
12510 if($Skip==1) {
12511 return 0;
12512 }
12513 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012514 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012515 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012516 { # user defined types
12517 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12518
12519 if(not $TypesList{$CName})
12520 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012521 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12522 {
12523 $CName=~s/\A\Q$NS\E\:\://g;
12524 }
12525
12526 if(not $TypesList{$CName})
12527 {
12528 my $Found = 0;
12529
12530 while($CName=~s/\:\:.+?\Z//)
12531 {
12532 if($TypesList{$CName})
12533 {
12534 $Found = 1;
12535 last;
12536 }
12537 }
12538
12539 if(not $Found) {
12540 return 0;
12541 }
12542 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012543 }
12544 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012545
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012546 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12547 { # non-target symbols
12548 return 0;
12549 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012550 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012551 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012552 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12553 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012554 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012555 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12556 { # inline virtual methods
12557 if($Type=~/InlineVirt/) {
12558 return 1;
12559 }
12560 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12561 if(not $Allocable)
12562 { # check bases
12563 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12564 {
12565 if(not isCopyingClass($DCId, $LibVersion))
12566 { # exists a derived class without default c-tor
12567 $Allocable=1;
12568 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 }
12571 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012572 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012573 return 0;
12574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012576 else
12577 { # inline non-virtual methods
12578 return 0;
12579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581 }
12582 }
12583 return 1;
12584}
12585
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012586sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012588 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12590 {
12591 if(link_symbol($Symbol, 1, "+Deps"))
12592 { # linker can find a new symbol
12593 # in the old-version library
12594 # So, it's not a new symbol
12595 next;
12596 }
12597 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012598 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599 next;
12600 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012601 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 }
12603}
12604
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012605sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012607 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12609 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012610 if(link_symbol($Symbol, 2, "+Deps"))
12611 { # linker can find an old symbol
12612 # in the new-version library
12613 next;
12614 }
12615 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012616 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617 next;
12618 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012619 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012620 }
12621}
12622
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012623sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012625 my $Level = $_[0];
12626 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012627 { # checking added symbols
12628 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012629 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012630 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012631 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012633 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012634 { # checking removed symbols
12635 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012636 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012637 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012638 { # skip v-tables for templates, that should not be imported by applications
12639 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012640 if(my $CName = $VTableClass{$Symbol})
12641 {
12642 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12643 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012644 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012645 next;
12646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012647 }
12648 }
12649 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012650 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012651 }
12652 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12653 { # symbols for pure virtual methods cannot be called by clients
12654 next;
12655 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012656 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657 }
12658}
12659
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012660sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012661{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012662 my ($LibVersion, $V) = @_;
12663 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12664 return $Cache{"checkDump"}{$LibVersion}{$V};
12665 }
12666 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012667}
12668
12669sub detectAdded_H($)
12670{
12671 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012672 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12673 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012674 if($Level eq "Source")
12675 { # remove symbol version
12676 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12677 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012678
12679 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12680 { # skip artificial constructors
12681 next;
12682 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012683 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012684 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12685 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012686 next;
12687 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012688 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012689 next;
12690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012691 if(not defined $CompleteSignature{1}{$Symbol}
12692 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12693 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012694 if($UsedDump{2}{"SrcBin"})
12695 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012696 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012697 { # support for old and different (!) ABI dumps
12698 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12699 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012700 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012701 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012702 {
12703 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12704 {
12705 if($Lang eq "C")
12706 { # support for old ABI dumps: missed extern "C" functions
12707 next;
12708 }
12709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012710 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012711 else
12712 {
12713 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012714 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012715 next;
12716 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012717 }
12718 }
12719 }
12720 }
12721 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012722 }
12723 }
12724}
12725
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012726sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012728 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012729 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12730 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012731 if($Level eq "Source")
12732 { # remove symbol version
12733 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12734 $Symbol=$SN;
12735 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012736 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12737 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012738 next;
12739 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012740 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012741 next;
12742 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012743 if(not defined $CompleteSignature{2}{$Symbol}
12744 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012745 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012746 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012747 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012748 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012749 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012750 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12751 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012752 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012753 if($CheckHeadersOnly)
12754 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012755 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12756 {
12757 if($Lang eq "C")
12758 { # support for old ABI dumps: missed extern "C" functions
12759 next;
12760 }
12761 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012762 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012763 else
12764 {
12765 if(not link_symbol($Symbol, 1, "-Deps"))
12766 { # skip removed inline symbols
12767 next;
12768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012769 }
12770 }
12771 }
12772 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012773 if(not checkDump(1, "2.15"))
12774 {
12775 if($Symbol=~/_IT_E\Z/)
12776 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12777 next;
12778 }
12779 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012780 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12781 {
12782 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12783 {
12784 if(defined $Constants{2}{$Short})
12785 {
12786 my $Val = $Constants{2}{$Short}{"Value"};
12787 if(defined $Func_ShortName{2}{$Val})
12788 { # old name defined to new
12789 next;
12790 }
12791 }
12792 }
12793
12794 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012795 $RemovedInt{$Level}{$Symbol} = 1;
12796 if($Level eq "Source")
12797 { # search for a source-compatible equivalent
12798 setAlternative($Symbol, $Level);
12799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012800 }
12801 }
12802}
12803
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012804sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012805{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012806 my $Level = $_[0];
12807 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 { # checking added symbols
12809 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012810 next if($CompleteSignature{2}{$Symbol}{"Private"});
12811 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012812 if($Level eq "Binary")
12813 {
12814 if($CompleteSignature{2}{$Symbol}{"InLine"})
12815 {
12816 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12817 { # skip inline non-virtual functions
12818 next;
12819 }
12820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012821 }
12822 else
12823 { # Source
12824 if($SourceAlternative_B{$Symbol}) {
12825 next;
12826 }
12827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012828 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012830 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012831 { # checking removed symbols
12832 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012833 next if($CompleteSignature{1}{$Symbol}{"Private"});
12834 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012835 if($Level eq "Binary")
12836 {
12837 if($CompleteSignature{1}{$Symbol}{"InLine"})
12838 {
12839 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12840 { # skip inline non-virtual functions
12841 next;
12842 }
12843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012844 }
12845 else
12846 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012847 if(my $Alt = $SourceAlternative{$Symbol})
12848 {
12849 if(defined $CompleteSignature{1}{$Alt}
12850 and $CompleteSignature{1}{$Symbol}{"Const"})
12851 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012852 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012853 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012854 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012855 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012856 }
12857 else
12858 { # do NOT show removed symbol
12859 next;
12860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861 }
12862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012863 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012864 }
12865}
12866
12867sub addParamNames($)
12868{
12869 my $LibraryVersion = $_[0];
12870 return if(not keys(%AddIntParams));
12871 my $SecondVersion = $LibraryVersion==1?2:1;
12872 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12873 {
12874 next if(not keys(%{$AddIntParams{$Interface}}));
12875 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012876 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012877 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12878 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012879 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12881 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12882 {
12883 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12884 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12885 }
12886 }
12887 else {
12888 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12889 }
12890 }
12891 }
12892 }
12893}
12894
12895sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012896{ # detect changed typedefs to show
12897 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012898 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12899 {
12900 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012901 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12902 if(not $BName1 or isAnon($BName1)) {
12903 next;
12904 }
12905 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12906 if(not $BName2 or isAnon($BName2)) {
12907 next;
12908 }
12909 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012910 $ChangedTypedef{$Typedef} = 1;
12911 }
12912 }
12913}
12914
12915sub get_symbol_suffix($$)
12916{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 my ($Symbol, $Full) = @_;
12918 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012919 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012921 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012922 if(not $Full) {
12923 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12924 }
12925 return $Suffix;
12926}
12927
12928sub get_symbol_prefix($$)
12929{
12930 my ($Symbol, $LibVersion) = @_;
12931 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12932 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12933 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012934 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012935 }
12936 return $ShortName;
12937}
12938
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012939sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012940{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012941 my $Symbol = $_[0];
12942 my $PSymbol = $Symbol;
12943 if(not defined $CompleteSignature{2}{$PSymbol}
12944 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12945 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12946 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012947 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012949 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012950 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012951 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12952 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012953 {
12954 if(defined $CompleteSignature{2}{$PSymbol}
12955 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12956 {
12957 $SourceAlternative{$Symbol} = $PSymbol;
12958 $SourceAlternative_B{$PSymbol} = $Symbol;
12959 if(not defined $CompleteSignature{1}{$PSymbol}
12960 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12961 $SourceReplacement{$Symbol} = $PSymbol;
12962 }
12963 }
12964 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012965 }
12966 else
12967 {
12968 foreach my $Sp ("KV", "VK", "K", "V")
12969 {
12970 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12971 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12972 {
12973 if(defined $CompleteSignature{2}{$PSymbol}
12974 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12975 {
12976 $SourceAlternative{$Symbol} = $PSymbol;
12977 $SourceAlternative_B{$PSymbol} = $Symbol;
12978 if(not defined $CompleteSignature{1}{$PSymbol}
12979 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12980 $SourceReplacement{$Symbol} = $PSymbol;
12981 }
12982 }
12983 }
12984 $PSymbol = $Symbol;
12985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 }
12987 }
12988 }
12989 return "";
12990}
12991
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012992sub getSymKind($$)
12993{
12994 my ($Symbol, $LibVersion) = @_;
12995 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12996 {
12997 return "Global_Data";
12998 }
12999 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13000 {
13001 return "Method";
13002 }
13003 return "Function";
13004}
13005
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013006sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013007{
13008 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013009 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013010
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013011 mergeBases($Level);
13012
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013013 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013015 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013016 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 next;
13018 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013019 if(defined $CompleteSignature{1}{$Symbol}
13020 and $CompleteSignature{1}{$Symbol}{"Header"})
13021 { # double-check added symbol
13022 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013023 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013024 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013025 next;
13026 }
13027 if($Symbol=~/\A(_Z|\?)/)
13028 { # C++
13029 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13030 }
13031 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13032 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013033 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13034 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013035 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013036 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013037 {
13038 if($TName_Tid{1}{$AffectedClass_Name})
13039 { # class should exist in previous version
13040 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13041 { # old v-table is NOT copied by old applications
13042 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13043 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013044 "Target"=>get_Signature($Symbol, 2),
13045 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013046 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013049 }
13050 }
13051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013052 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13053 { # check all removed exported symbols
13054 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013055 next;
13056 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013057 if(defined $CompleteSignature{2}{$Symbol}
13058 and $CompleteSignature{2}{$Symbol}{"Header"})
13059 { # double-check removed symbol
13060 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013061 }
13062 if($CompleteSignature{1}{$Symbol}{"Private"})
13063 { # skip private methods
13064 next;
13065 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013066 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013067 next;
13068 }
13069 $CheckedSymbols{$Level}{$Symbol} = 1;
13070 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13071 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013072 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13073 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013074 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013075 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13076 {
13077 if($TName_Tid{2}{$AffectedClass_Name})
13078 { # class should exist in newer version
13079 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13080 { # old v-table is NOT copied by old applications
13081 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13082 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013083 "Target"=>get_Signature($OverriddenMethod, 1),
13084 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013085 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013087 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013088 }
13089 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013090 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013091 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013092 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013093 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013094 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013095 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013096 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013097 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013098 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013099 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013100 {
13101 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13102 "Target"=>$tr_name{$Symbol},
13103 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013104 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013105 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 else
13107 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013108 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 "Target"=>$tr_name{$Symbol},
13110 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013111 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013112 }
13113 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013114 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013115 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013116 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013117 {
13118 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13119 "Target"=>$tr_name{$Symbol},
13120 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013121 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013122 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013123 else
13124 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013125 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013126 "Target"=>$tr_name{$Symbol},
13127 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013128 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013129 }
13130 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013131 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13132 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13133 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13134 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13135 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013136 {
13137 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013138 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013139 $ProblemType = "Global_Data_Symbol_Changed_Type";
13140 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013141 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13142 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013143 "Old_Type"=>$RTName1,
13144 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013145 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013146 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013147 }
13148 }
13149 }
13150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013152 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013154 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013155 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013156 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013157 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013158 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13159 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013160 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013161 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013162 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013163 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 }
13165 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013166 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13167 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013168 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013169 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013171 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013172 }
13173 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013174 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013175 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013176 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013179 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013180 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013181 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013182 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013184 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013185 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013186 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013188 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013189 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013190 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013191 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013193 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013194 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013195 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013197 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013198 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013199 { # "volatile" to non-"volatile"
13200
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013201 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013202 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013203 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013204 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013205 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013206 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013207 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013208 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013209 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013210 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013211 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013212 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013213 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013214 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013216 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013217 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013218 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13219 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013220 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013221 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013222 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223 }
13224 }
13225 }
13226 }
13227 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013228 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13229 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013230 $CurrentSymbol = $Symbol;
13231
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013232 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13233 if($Level eq "Source")
13234 { # remove symbol version
13235 $Symbol=$SN;
13236 }
13237 else
13238 { # Binary
13239 if(not $SV)
13240 { # symbol without version
13241 if(my $VSym = $SymVer{1}{$Symbol})
13242 { # the symbol is linked with versioned symbol
13243 if($CompleteSignature{2}{$VSym}{"MnglName"})
13244 { # show report for symbol@ver only
13245 next;
13246 }
13247 elsif(not link_symbol($VSym, 2, "-Deps"))
13248 { # changed version: sym@v1 to sym@v2
13249 # do NOT show report for symbol
13250 next;
13251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
13253 }
13254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013255 my $PSymbol = $Symbol;
13256 if($Level eq "Source"
13257 and my $S = $SourceReplacement{$Symbol})
13258 { # take a source-compatible replacement function
13259 $PSymbol = $S;
13260 }
13261 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 { # private symbols
13263 next;
13264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013265 if(not defined $CompleteSignature{1}{$Symbol}
13266 or not defined $CompleteSignature{2}{$PSymbol})
13267 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013268 next;
13269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013270 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13271 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13272 { # no mangled name
13273 next;
13274 }
13275 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13276 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 { # without a header
13278 next;
13279 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013280
13281 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13282 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13283 { # became pure
13284 next;
13285 }
13286 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13287 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13288 { # became non-pure
13289 next;
13290 }
13291
13292 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13293 { # exported, target, inline virtual and pure virtual
13294 next;
13295 }
13296 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13297 { # exported, target, inline virtual and pure virtual
13298 next;
13299 }
13300
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013301 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013302 {
13303 if($CompleteSignature{1}{$Symbol}{"Data"}
13304 and $CompleteSignature{2}{$PSymbol}{"Data"})
13305 {
13306 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13307 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13308 if(defined $Value1)
13309 {
13310 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13311 if(defined $Value2)
13312 {
13313 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13314 if($Value1 ne $Value2)
13315 {
13316 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13317 "Old_Value"=>$Value1,
13318 "New_Value"=>$Value2,
13319 "Target"=>get_Signature($Symbol, 1) );
13320 }
13321 }
13322 }
13323 }
13324 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013325
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013326 if($CompleteSignature{2}{$PSymbol}{"Private"})
13327 {
13328 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13329 "Target"=>get_Signature_M($PSymbol, 2) );
13330 }
13331 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13332 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13333 {
13334 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13335 "Target"=>get_Signature_M($PSymbol, 2) );
13336 }
13337 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13338 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13339 {
13340 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13341 "Target"=>get_Signature_M($PSymbol, 2) );
13342 }
13343
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013345 mergeVirtualTables($Symbol, $Level);
13346
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 if($COMPILE_ERRORS)
13348 { # if some errors occurred at the compiling stage
13349 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013351 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 { # missed information about parameters in newer version
13353 next;
13354 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013355 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013357 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 next;
13359 }
13360 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013364 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13365 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13367 "Target"=>get_Signature($Symbol, 1)
13368 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013369 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013371 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13372 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013373 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013374 "Target"=>get_Signature($Symbol, 1)
13375 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013377 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13378 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013380 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013382 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13383 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13384 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013386 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013387 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13388 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013390 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 my $ProblemType = "Virtual_Method_Position";
13392 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13393 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013394 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 if(isUsedClass($Class_Id, 1, $Level))
13396 {
13397 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013398 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013400 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13401 next;
13402 }
13403 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013404 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13406 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013407 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013409 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 }
13412 }
13413 }
13414 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013415 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13416 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013417 { # do NOT check type changes in pure virtuals
13418 next;
13419 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013420 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013421 if($Symbol=~/\A(_Z|\?)/
13422 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013425 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013426 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013427 }
13428 }
13429 else
13430 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013432 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013433 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13435 last if($PType2_Name eq "...");
13436 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13437 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013438 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013439 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013441 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13442 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013443 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13444 $ParamPos_Prev = "lost";
13445 }
13446 }
13447 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013448 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013449 }
13450 if($ParamPos_Prev eq "lost")
13451 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013452 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013453 {
13454 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013455 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013456 $ProblemType = "Added_Unnamed_Parameter";
13457 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013458 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013459 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013460 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013461 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013462 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013463 }
13464 else
13465 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013466 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013468 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013469 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13470 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013472 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013473 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013474 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013476 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013477 "Param_Type"=>$PType2_Name,
13478 "Old_Value"=>$PName_Old,
13479 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013480 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013481 }
13482 }
13483 else
13484 {
13485 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013486 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013487 $ProblemType = "Added_Middle_Unnamed_Parameter";
13488 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013489 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013490 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013491 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013492 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013493 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013494 }
13495 }
13496 }
13497 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013498 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013500 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013502 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013503 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013504 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013505 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013506 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013507 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13508 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013509 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013510 }
13511 }
13512 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013513 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013514 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013515 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013516 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13517 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013518 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13519 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013521 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013523 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13524 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013525 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13526 $ParamPos_New = "lost";
13527 }
13528 }
13529 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013530 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 }
13532 if($ParamPos_New eq "lost")
13533 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013534 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013535 {
13536 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013537 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013538 $ProblemType = "Removed_Unnamed_Parameter";
13539 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013540 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013541 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013542 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013543 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013544 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013545 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013546 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013548 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013549 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013550 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013551 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013552 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013554 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013555 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013556 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013557 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013558 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013559 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013560 "Old_Value"=>$PName,
13561 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013562 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013563 }
13564 }
13565 else
13566 {
13567 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013568 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013569 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013571 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013572 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013573 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013574 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013575 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 }
13577 }
13578 }
13579 }
13580 }
13581 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013582 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13583 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013584 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013585
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013586 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013588 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13589 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013590 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013591
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013592 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013594 if($SubProblemType eq "Return_Type_And_Size") {
13595 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13596 }
13597 elsif($SubProblemType eq "Return_Type_Format") {
13598 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13599 }
13600 else {
13601 $ProblemTypes{"Global_Data_Type"} = 1;
13602 }
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(my $RR = removedQual($Old_Value, $New_Value, "const"))
13610 { # const to non-const
13611 if($RR==2) {
13612 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13613 }
13614 else {
13615 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13616 }
13617 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013619 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13620 { # non-const to const
13621 if($RA==2) {
13622 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13623 }
13624 else {
13625 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13626 }
13627 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 }
13629 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013630 }
13631 else
13632 {
13633 # quals
13634 if($SubProblemType eq "Return_Type"
13635 or $SubProblemType eq "Return_Type_And_Size"
13636 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013637 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013638 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013639 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013640 if(addedQual($Old_Value, $New_Value, "volatile"))
13641 {
13642 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13643 if($Level ne "Source"
13644 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13645 $ProblemTypes{"Return_Type"} = 1;
13646 }
13647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013648 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013649 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13650 {
13651 if($RA==2) {
13652 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13653 }
13654 else {
13655 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13656 }
13657 if($Level ne "Source"
13658 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13659 $ProblemTypes{"Return_Type"} = 1;
13660 }
13661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013662 }
13663 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013664 if($Level eq "Binary"
13665 and not $CompleteSignature{1}{$Symbol}{"Data"})
13666 {
13667 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13668 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13669 { # if one of the architectures is unknown
13670 # then set other arhitecture to unknown too
13671 ($Arch1, $Arch2) = ("unknown", "unknown");
13672 }
13673 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013674 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013675 {
13676 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13677 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13678 }
13679 else
13680 {
13681 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13682 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13683 }
13684
13685 if($SubProblemType eq "Return_Type_Became_Void")
13686 {
13687 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13688 { # parameters stack has been affected
13689 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013690 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013691 }
13692 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013693 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013694 }
13695 }
13696 }
13697 elsif($SubProblemType eq "Return_Type_From_Void")
13698 {
13699 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13700 { # parameters stack has been affected
13701 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013702 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013703 }
13704 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013705 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013706 }
13707 }
13708 }
13709 elsif($SubProblemType eq "Return_Type"
13710 or $SubProblemType eq "Return_Type_And_Size"
13711 or $SubProblemType eq "Return_Type_Format")
13712 {
13713 if($Conv1{"Method"} ne $Conv2{"Method"})
13714 {
13715 if($Conv1{"Method"} eq "stack")
13716 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013717 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013718 }
13719 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013720 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013721 }
13722 }
13723 else
13724 {
13725 if($Conv1{"Method"} eq "reg")
13726 {
13727 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13728 {
13729 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013730 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013731 }
13732 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013733 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013734 }
13735 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013736 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013737 }
13738 }
13739 }
13740 }
13741 }
13742 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013743
13744 if(not keys(%ProblemTypes))
13745 { # default
13746 $ProblemTypes{$SubProblemType} = 1;
13747 }
13748
13749 foreach my $ProblemType (keys(%ProblemTypes))
13750 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013751 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013753 }
13754 if($ReturnType1_Id and $ReturnType2_Id)
13755 {
13756 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013757 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13758
13759 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013760
13761 if($CompleteSignature{1}{$Symbol}{"Data"})
13762 {
13763 if($Level eq "Binary")
13764 {
13765 if(get_PLevel($ReturnType1_Id, 1)==0)
13766 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013767 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013768 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013769
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013770 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13771 {
13772 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013773 {
13774 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13775 {
13776 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13777 last;
13778 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013779 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013780 }
13781 }
13782 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013783 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013784 {
13785 if(defined $GlobalDataObject{1}{$Symbol}
13786 and defined $GlobalDataObject{2}{$Symbol})
13787 {
13788 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13789 my $New_Size = $GlobalDataObject{2}{$Symbol};
13790 if($Old_Size!=$New_Size)
13791 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013792 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013793 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013794 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013795 }
13796 }
13797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013798 }
13799 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013800
13801 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013803 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013804 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013805 my $NewLocation = "retval";
13806 if($SubLocation and $SubLocation ne "retval") {
13807 $NewLocation = "retval->".$SubLocation;
13808 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013809 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13810 }
13811 }
13812
13813 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13814 {
13815 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13816 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013817 my $NewLocation = "retval";
13818 if($SubLocation and $SubLocation ne "retval") {
13819 $NewLocation = "retval->".$SubLocation;
13820 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013821 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013822 }
13823 }
13824 }
13825
13826 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013827 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13828 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13829 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013830 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013831 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013832 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13833 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013834 if($ThisPtr1_Id and $ThisPtr2_Id)
13835 {
13836 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013837 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13838 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013840 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013841 {
13842 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013843 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013844 }
13845 }
13846 }
13847 }
13848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013849 if($Level eq "Binary") {
13850 mergeVTables($Level);
13851 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013852 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13853 $CheckedSymbols{$Level}{$Symbol} = 1;
13854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013855}
13856
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013857sub rmQuals($$)
13858{
13859 my ($Value, $Qual) = @_;
13860 if(not $Qual) {
13861 return $Value;
13862 }
13863 if($Qual eq "all")
13864 { # all quals
13865 $Qual = "const|volatile|restrict";
13866 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013867 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013868 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013869 }
13870 return $Value;
13871}
13872
13873sub cmpBTypes($$$$)
13874{
13875 my ($T1, $T2, $V1, $V2) = @_;
13876 $T1 = uncover_typedefs($T1, $V1);
13877 $T2 = uncover_typedefs($T2, $V2);
13878 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13879}
13880
13881sub addedQual($$$)
13882{
13883 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013884 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013885}
13886
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013887sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013888{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013889 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013890 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013891}
13892
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013893sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013894{
13895 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13896 $Old_Value = uncover_typedefs($Old_Value, $V1);
13897 $New_Value = uncover_typedefs($New_Value, $V2);
13898 if($Old_Value eq $New_Value)
13899 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013900 return 0;
13901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013902 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013903 { # without a qual
13904 return 0;
13905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013906 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013907 { # became non-qual
13908 return 1;
13909 }
13910 else
13911 {
13912 my @BQ1 = getQualModel($Old_Value, $Qual);
13913 my @BQ2 = getQualModel($New_Value, $Qual);
13914 foreach (0 .. $#BQ1)
13915 { # removed qual
13916 if($BQ1[$_]==1
13917 and $BQ2[$_]!=1)
13918 {
13919 return 2;
13920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013921 }
13922 }
13923 return 0;
13924}
13925
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013926sub getQualModel($$)
13927{
13928 my ($Value, $Qual) = @_;
13929 if(not $Qual) {
13930 return $Value;
13931 }
13932
13933 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013934 while($Value=~/(\w+)/ and $1 ne $Qual) {
13935 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013936 }
13937 $Value=~s/[^\*\&\w]+//g;
13938
13939 # modeling
13940 # int*const*const == 011
13941 # int**const == 001
13942 my @Model = ();
13943 my @Elems = split(/[\*\&]/, $Value);
13944 if(not @Elems) {
13945 return (0);
13946 }
13947 foreach (@Elems)
13948 {
13949 if($_ eq $Qual) {
13950 push(@Model, 1);
13951 }
13952 else {
13953 push(@Model, 0);
13954 }
13955 }
13956
13957 return @Model;
13958}
13959
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013960my %StringTypes = map {$_=>1} (
13961 "char*",
13962 "char const*"
13963);
13964
13965my %CharTypes = map {$_=>1} (
13966 "char",
13967 "char const"
13968);
13969
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013970sub showVal($$$)
13971{
13972 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013973 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013974 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013975 if(substr($Value, 0, 2) eq "_Z")
13976 {
13977 if(my $Unmangled = $tr_name{$Value}) {
13978 return $Unmangled;
13979 }
13980 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013981 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013982 { # strings
13983 return "\"$Value\"";
13984 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013985 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013986 { # characters
13987 return "\'$Value\'";
13988 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013989 if($Value eq "")
13990 { # other
13991 return "\'\'";
13992 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013993 return $Value;
13994}
13995
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013996sub getRegs($$$)
13997{
13998 my ($LibVersion, $Symbol, $Pos) = @_;
13999
14000 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14001 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014002 my %Regs = ();
14003 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14004 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014005 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014006 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14007 }
14008 }
14009
14010 return join(", ", sort keys(%Regs));
14011 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014012 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14013 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14014 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14015 {
14016 return "unknown";
14017 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014018
14019 return undef;
14020}
14021
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014022sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014023{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014024 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014025 if(not $Symbol) {
14026 return;
14027 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014028 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14029 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14030 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14031 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014032 if(not $PType1_Id
14033 or not $PType2_Id) {
14034 return;
14035 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014036
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014037 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014038 { # do not merge "this"
14039 if($PName1 eq "this" or $PName2 eq "this") {
14040 return;
14041 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014042 }
14043
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014044 my %Type1 = get_Type($PType1_Id, 1);
14045 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014046
14047 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14048
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014049 my %BaseType1 = get_BaseType($PType1_Id, 1);
14050 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014051
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014052 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014054 if($Level eq "Binary")
14055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014056 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014057 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14058 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14059 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14060 {
14061 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014062 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014063 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014064 }
14065 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14066 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14067 {
14068 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014069 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014070 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014072 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014073
14074 if(defined $UsedDump{1}{"DWARF"}
14075 and defined $UsedDump{2}{"DWARF"})
14076 {
14077 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14078 {
14079 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14080 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014081
14082 if($Old_Regs ne "unknown"
14083 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014084 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014085 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014086 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014087 if($Old_Regs ne $New_Regs)
14088 {
14089 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14090 "Target"=>$PName1,
14091 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14092 "Old_Value"=>$Old_Regs,
14093 "New_Value"=>$New_Regs );
14094 }
14095 }
14096 elsif($Old_Regs and not $New_Regs)
14097 {
14098 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014099 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014100 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014101 "Old_Value"=>$Old_Regs );
14102 }
14103 elsif(not $Old_Regs and $New_Regs)
14104 {
14105 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14106 "Target"=>$PName1,
14107 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014108 "New_Value"=>$New_Regs );
14109 }
14110 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014111
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014112 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14113 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14114 {
14115 if($Old_Offset ne $New_Offset)
14116 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014117 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14118 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14119
14120 $Old_Offset = $Old_Offset - $Start1;
14121 $New_Offset = $New_Offset - $Start2;
14122
14123 if($Old_Offset ne $New_Offset)
14124 {
14125 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14126 "Target"=>$PName1,
14127 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14128 "Old_Value"=>$Old_Offset,
14129 "New_Value"=>$New_Offset );
14130 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014131 }
14132 }
14133 }
14134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014135 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014136 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14137 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014138 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014139 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014140 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14141 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014142 if(not checkDump(1, "2.13")
14143 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014144 { # support for old ABI dumps
14145 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014146 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014147 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014148 and $Value_Old eq "false" and $Value_New eq "0")
14149 { # int class::method ( bool p = 0 );
14150 # old ABI dumps: "false"
14151 # new ABI dumps: "0"
14152 $Value_Old = "0";
14153 }
14154 }
14155 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014156 if(not checkDump(1, "2.18")
14157 and checkDump(2, "2.18"))
14158 { # support for old ABI dumps
14159 if(not defined $Value_Old
14160 and substr($Value_New, 0, 2) eq "_Z") {
14161 $Value_Old = $Value_New;
14162 }
14163 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014164 if(defined $Value_Old)
14165 {
14166 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14167 if(defined $Value_New)
14168 {
14169 $Value_New = showVal($Value_New, $PType2_Id, 2);
14170 if($Value_Old ne $Value_New)
14171 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014172 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014173 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014174 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014175 "Old_Value"=>$Value_Old,
14176 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014177 }
14178 }
14179 else
14180 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014181 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014183 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014184 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014185 }
14186 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014187 elsif(defined $Value_New)
14188 {
14189 $Value_New = showVal($Value_New, $PType2_Id, 2);
14190 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14191 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014192 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014193 "New_Value"=>$Value_New );
14194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014195 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014196
14197 if($ChkRnmd)
14198 {
14199 if($PName1 and $PName2 and $PName1 ne $PName2
14200 and $PType1_Id!=-1 and $PType2_Id!=-1
14201 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14202 { # except unnamed "..." value list (Id=-1)
14203 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14204 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014205 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014206 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14207 "Old_Value"=>$PName1,
14208 "New_Value"=>$PName2,
14209 "New_Signature"=>get_Signature($Symbol, 2) );
14210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014211 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014212
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014213 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014214 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014215
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014216 foreach my $SubProblemType (keys(%SubProblems))
14217 { # add new problems, remove false alarms
14218 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14219 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014220
14221 # quals
14222 if($SubProblemType eq "Parameter_Type"
14223 or $SubProblemType eq "Parameter_Type_And_Size"
14224 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014225 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014226 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014227 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014228 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014229 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014230 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014231 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14232 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14233 }
14234 }
14235 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14236 {
14237 if(removedQual($Old_Value, $New_Value, "volatile")) {
14238 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014239 }
14240 }
14241 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14242 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14243 { # int to "int const"
14244 delete($SubProblems{$SubProblemType});
14245 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014246 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014247 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14248 { # "int const" to int
14249 delete($SubProblems{$SubProblemType});
14250 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014251 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14252 { # "const" to non-"const"
14253 if($RR==2) {
14254 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14255 }
14256 else {
14257 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14258 }
14259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014260 }
14261 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014262
14263 if($Level eq "Source")
14264 {
14265 foreach my $SubProblemType (keys(%SubProblems))
14266 {
14267 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14268 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14269
14270 if($SubProblemType eq "Parameter_Type")
14271 {
14272 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14273 delete($SubProblems{$SubProblemType});
14274 }
14275 }
14276 }
14277 }
14278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014279 foreach my $SubProblemType (keys(%SubProblems))
14280 { # modify/register problems
14281 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14282 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014283 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14284 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014285
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014286 my $NewProblemType = $SubProblemType;
14287 if($Old_Value eq "..." and $New_Value ne "...")
14288 { # change from "..." to "int"
14289 if($ParamPos1==0)
14290 { # ISO C requires a named argument before "..."
14291 next;
14292 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014293 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014294 }
14295 elsif($New_Value eq "..." and $Old_Value ne "...")
14296 { # change from "int" to "..."
14297 if($ParamPos2==0)
14298 { # ISO C requires a named argument before "..."
14299 next;
14300 }
14301 $NewProblemType = "Parameter_Became_VaList";
14302 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014303 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014304 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014305 {
14306 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014307 if($Arch1 eq "unknown"
14308 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014309 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014310 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014311 ($Arch1, $Arch2) = ("unknown", "unknown");
14312 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014313 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014314 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014315 { # real
14316 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14317 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14318 }
14319 else
14320 { # model
14321 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14322 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14323 }
14324 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014325 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014326 if($Conv1{"Method"} eq "stack")
14327 {
14328 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14329 $NewProblemType = "Parameter_Type_And_Stack";
14330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014331 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014332 elsif($Conv1{"Method"} eq "reg")
14333 {
14334 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14335 $NewProblemType = "Parameter_Type_And_Register";
14336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014337 }
14338 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014339 elsif($Conv1{"Method"} ne "unknown"
14340 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014341 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014342 if($Conv1{"Method"} eq "stack") {
14343 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014344 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014345 elsif($Conv1{"Method"} eq "register") {
14346 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014347 }
14348 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014349 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14350 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014352 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014353 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014354 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014355 "New_Signature"=>get_Signature($Symbol, 2) );
14356 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014357 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014361 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014362 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14363 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014364 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014365 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 {
14367 my $NewProblemType = $SubProblemType;
14368 if($SubProblemType eq "DataType_Size")
14369 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014370 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014371 { # stack has been affected
14372 $NewProblemType = "DataType_Size_And_Stack";
14373 }
14374 }
14375 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014376 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014377 }
14378 }
14379}
14380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014381sub find_ParamPair_Pos_byName($$$)
14382{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014383 my ($Name, $Symbol, $LibVersion) = @_;
14384 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014385 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014386 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14387 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014388 {
14389 return $ParamPos;
14390 }
14391 }
14392 return "lost";
14393}
14394
14395sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14396{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014397 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014398 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014399 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 {
14401 next if($Order eq "backward" and $ParamPos>$MediumPos);
14402 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014403 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14404 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014405 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 push(@Positions, $ParamPos);
14407 }
14408 }
14409 return @Positions;
14410}
14411
14412sub getTypeIdByName($$)
14413{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014414 my ($TypeName, $LibVersion) = @_;
14415 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014416}
14417
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014418sub diffTypes($$$)
14419{
14420 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14421 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14422 }
14423 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14424 { # skip recursive declarations
14425 return 0;
14426 }
14427
14428 pushType($_[0], $_[1], \@RecurTypes_Diff);
14429 my $Diff = diffTypes_I(@_);
14430 pop(@RecurTypes_Diff);
14431
14432 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14433}
14434
14435sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014437 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014438
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014439 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14440 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014442 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14443 { # equal types
14444 return 0;
14445 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014446 if($Type1_Pure{"Name"} eq "void")
14447 { # from void* to something
14448 return 0;
14449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014450 if($Type1_Pure{"Name"}=~/\*/
14451 or $Type2_Pure{"Name"}=~/\*/)
14452 { # compared in detectTypeChange()
14453 return 0;
14454 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014455
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014456 my %FloatType = map {$_=>1} (
14457 "float",
14458 "double",
14459 "long double"
14460 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014461
14462 my $T1 = $Type1_Pure{"Type"};
14463 my $T2 = $Type2_Pure{"Type"};
14464
14465 if($T1 eq "Struct"
14466 and $T2 eq "Class")
14467 { # compare as data structures
14468 $T2 = "Struct";
14469 }
14470
14471 if($T1 eq "Class"
14472 and $T2 eq "Struct")
14473 { # compare as data structures
14474 $T1 = "Struct";
14475 }
14476
14477 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014478 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014479 if($T1 eq "Intrinsic"
14480 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014481 { # "int" to "enum"
14482 return 0;
14483 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014484 elsif($T2 eq "Intrinsic"
14485 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014486 { # "enum" to "int"
14487 return 0;
14488 }
14489 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014490 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014491 # ...
14492 return 1;
14493 }
14494 }
14495 else
14496 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014497 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498 {
14499 if($FloatType{$Type1_Pure{"Name"}}
14500 or $FloatType{$Type2_Pure{"Name"}})
14501 { # "float" to "double"
14502 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014503 if($Level eq "Source")
14504 { # Safe
14505 return 0;
14506 }
14507 else {
14508 return 1;
14509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 }
14511 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014512 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014513 {
14514 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14515 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014516 if(not @Membs1
14517 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014518 { # private
14519 return 0;
14520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 if($#Membs1!=$#Membs2)
14522 { # different number of elements
14523 return 1;
14524 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014525 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 {
14527 foreach my $Pos (@Membs1)
14528 { # compare elements by name and value
14529 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14530 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14531 { # different names
14532 return 1;
14533 }
14534 }
14535 }
14536 else
14537 {
14538 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014539 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014540 if($Level eq "Source")
14541 {
14542 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14543 { # different names
14544 return 1;
14545 }
14546 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014547
14548 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14549 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14550
14551 if($MT1{"Name"} ne $MT2{"Name"}
14552 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14553 {
14554 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14555 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14556
14557 if($PL1 ne $PL2)
14558 { # different pointer level
14559 return 1;
14560 }
14561
14562 # compare base types
14563 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14564 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14565
14566 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14567 { # different types
14568 return 1;
14569 }
14570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014571 }
14572 }
14573 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014574 else
14575 {
14576 # TODO: arrays, etc.
14577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014578 }
14579 return 0;
14580}
14581
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014582sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014584 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014585 if(not $Type1_Id or not $Type2_Id) {
14586 return ();
14587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014589 my %Type1 = get_Type($Type1_Id, 1);
14590 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014591 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14592 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14593 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14594 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 +040014595
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014596 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14597 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014598 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14599 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14600 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14601 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14602 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14603 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14604 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014605 if($Type1{"Name"} eq $Type2{"Name"})
14606 {
14607 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14608 { # will be reported in mergeTypes() as typedef problem
14609 return ();
14610 }
14611 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14612 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14613 if(%Typedef_1 and %Typedef_2)
14614 {
14615 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14616 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14617 { # const Typedef
14618 return ();
14619 }
14620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 }
14622 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14623 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014624 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014625 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14626 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 {
14628 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14629 "Old_Value"=>$Type1_Base{"Name"},
14630 "New_Value"=>$Type2_Base{"Name"},
14631 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014632 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014633 }
14634 else
14635 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014636 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014637 { # format change
14638 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14639 "Old_Value"=>$Type1_Base{"Name"},
14640 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014641 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014642 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014643 }
14644 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14645 {
14646 %{$LocalProblems{$Prefix."_BaseType"}}=(
14647 "Old_Value"=>$Type1_Base{"Name"},
14648 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014649 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014650 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014651 }
14652 }
14653 }
14654 }
14655 elsif($Type1{"Name"} ne $Type2{"Name"})
14656 { # type change
14657 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14658 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014659 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660 and $Type1_Pure{"Name"} eq "void")
14661 {
14662 %{$LocalProblems{"Return_Type_From_Void"}}=(
14663 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014664 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014666 elsif($Prefix eq "Return"
14667 and $Type2_Pure{"Name"} eq "void")
14668 {
14669 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14670 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014671 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014673 else
14674 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014675 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014676 and $Type1{"Size"} and $Type2{"Size"}
14677 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014678 {
14679 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14680 "Old_Value"=>$Type1{"Name"},
14681 "New_Value"=>$Type2{"Name"},
14682 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014683 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014684 }
14685 else
14686 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014687 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014688 { # format change
14689 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14690 "Old_Value"=>$Type1{"Name"},
14691 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014692 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014693 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014694 }
14695 elsif(tNameLock($Type1_Id, $Type2_Id))
14696 { # FIXME: correct this condition
14697 %{$LocalProblems{$Prefix."_Type"}}=(
14698 "Old_Value"=>$Type1{"Name"},
14699 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014700 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014701 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014702 }
14703 }
14704 }
14705 }
14706 }
14707 if($Type1_PLevel!=$Type2_PLevel)
14708 {
14709 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14710 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014712 if($Level eq "Source")
14713 {
14714 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014715 "Old_Value"=>$Type1_PLevel,
14716 "New_Value"=>$Type2_PLevel);
14717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014718 else
14719 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014720 if($Type2_PLevel>$Type1_PLevel)
14721 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014722 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14723 "Old_Value"=>$Type1_PLevel,
14724 "New_Value"=>$Type2_PLevel);
14725 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014726 else
14727 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014728 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14729 "Old_Value"=>$Type1_PLevel,
14730 "New_Value"=>$Type2_PLevel);
14731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014732 }
14733 }
14734 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014735 if($Type1_Pure{"Type"} eq "Array"
14736 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014737 { # base_type[N] -> base_type[N]
14738 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014739 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014740 foreach my $SubProblemType (keys(%SubProblems))
14741 {
14742 $SubProblemType=~s/_Type/_BaseType/g;
14743 next if(defined $LocalProblems{$SubProblemType});
14744 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14745 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14746 }
14747 }
14748 }
14749 return %LocalProblems;
14750}
14751
14752sub tNameLock($$)
14753{
14754 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014755 my $Changed = 0;
14756 if(differentDumps("G"))
14757 { # different GCC versions
14758 $Changed = 1;
14759 }
14760 elsif(differentDumps("V"))
14761 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014762 if(not checkDump(1, "2.20")
14763 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014764 { # latest names update
14765 # 2.6: added restrict qualifier
14766 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014767 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014768 $Changed = 1;
14769 }
14770 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014771
14772 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14773 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14774
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014775 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14776 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14777
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014778 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014779 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014780 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014781 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014782 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014784 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014785 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014786 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014787 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014788 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14789 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14790 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014791 { # equal base types
14792 return 0;
14793 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014794
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014795 if(not checkDump(1, "2.13")
14796 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014797 { # broken array names in ABI dumps < 2.13
14798 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014799 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014800 return 0;
14801 }
14802 }
14803
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014804 if(not checkDump(1, "2.6")
14805 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014806 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014807 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014808 and $TN2=~/\brestrict\b/) {
14809 return 0;
14810 }
14811 }
14812
14813 if(not checkDump(1, "2.20")
14814 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014815 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014816 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14817 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014818 return 0;
14819 }
14820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014821 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014822 else
14823 {
14824 # typedef struct {...} type_t
14825 # typedef struct type_t {...} type_t
14826 if(index($TN1, " ".$TN2)!=-1)
14827 {
14828 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14829 return 0;
14830 }
14831 }
14832 if(index($TN2, " ".$TN1)!=-1)
14833 {
14834 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14835 return 0;
14836 }
14837 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014838
14839 if($TT1 eq "FuncPtr"
14840 and $TT2 eq "FuncPtr")
14841 {
14842 my $TN1_C = $TN1;
14843 my $TN2_C = $TN2;
14844
14845 $TN1_C=~s/\b(struct|union) //g;
14846 $TN2_C=~s/\b(struct|union) //g;
14847
14848 if($TN1_C eq $TN2_C) {
14849 return 0;
14850 }
14851 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014852 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014853
14854 my ($N1, $N2) = ($TN1, $TN2);
14855 $N1=~s/\b(struct|union) //g;
14856 $N2=~s/\b(struct|union) //g;
14857
14858 if($N1 eq $N2)
14859 { # QList<struct QUrl> and QList<QUrl>
14860 return 0;
14861 }
14862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014863 return 1;
14864}
14865
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014866sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014867{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014868 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014869 if(defined $Cache{"differentDumps"}{$Check}) {
14870 return $Cache{"differentDumps"}{$Check};
14871 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014872 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014873 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014874 if($Check eq "G")
14875 {
14876 if(getGccVersion(1) ne getGccVersion(2))
14877 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014878 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014879 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014880 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014881 if($Check eq "V")
14882 {
14883 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14884 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14885 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014886 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014890 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014891}
14892
14893sub formatVersion($$)
14894{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014895 my ($V, $Digits) = @_;
14896 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014897 return join(".", splice(@Elems, 0, $Digits));
14898}
14899
14900sub htmlSpecChars($)
14901{
14902 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014903 if(not $Str) {
14904 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014906 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14907 $Str=~s/</&lt;/g;
14908 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14909 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014910 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14911 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014913 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014914 $Str=~s/\n/<br\/>/g;
14915 $Str=~s/\"/&quot;/g;
14916 $Str=~s/\'/&#39;/g;
14917 return $Str;
14918}
14919
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014920sub xmlSpecChars($)
14921{
14922 my $Str = $_[0];
14923 if(not $Str) {
14924 return $Str;
14925 }
14926
14927 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14928 $Str=~s/</&lt;/g;
14929 $Str=~s/>/&gt;/g;
14930
14931 $Str=~s/\"/&quot;/g;
14932 $Str=~s/\'/&#39;/g;
14933
14934 return $Str;
14935}
14936
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014937sub xmlSpecChars_R($)
14938{
14939 my $Str = $_[0];
14940 if(not $Str) {
14941 return $Str;
14942 }
14943
14944 $Str=~s/&amp;/&/g;
14945 $Str=~s/&lt;/</g;
14946 $Str=~s/&gt;/>/g;
14947
14948 $Str=~s/&quot;/"/g;
14949 $Str=~s/&#39;/'/g;
14950
14951 return $Str;
14952}
14953
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014954sub black_name($)
14955{
14956 my $Name = $_[0];
14957 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14958}
14959
14960sub highLight_Signature($)
14961{
14962 my $Signature = $_[0];
14963 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14964}
14965
14966sub highLight_Signature_Italic_Color($)
14967{
14968 my $Signature = $_[0];
14969 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14970}
14971
14972sub separate_symbol($)
14973{
14974 my $Symbol = $_[0];
14975 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14976 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14977 ($Name, $Spec, $Ver) = ($1, $2, $3);
14978 }
14979 return ($Name, $Spec, $Ver);
14980}
14981
14982sub cut_f_attrs($)
14983{
14984 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14985 return $2;
14986 }
14987 return "";
14988}
14989
14990sub highLight_Signature_PPos_Italic($$$$$)
14991{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014992 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14993 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014994 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14995 my $Return = "";
14996 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14997 $Return = $2;
14998 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014999 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015001 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015002 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015003 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015004 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015006 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015007 }
15008 return $Signature;
15009 }
15010 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15011 $Begin.=" " if($Begin!~/ \Z/);
15012 $End = cut_f_attrs($Signature);
15013 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015014 my ($Short, $Params) = split_Signature($Signature);
15015 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015016 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015017 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015018 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015019 $Part=~s/\A\s+|\s+\Z//g;
15020 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15021 if($Part=~/\([\*]+(\w+)\)/i) {
15022 $ParamName = $1;#func-ptr
15023 }
15024 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15025 $ParamName = $1;
15026 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015027 if(not $ParamName)
15028 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015029 push(@Parts, $Part_Styled);
15030 next;
15031 }
15032 if($ItalicParams and not $TName_Tid{1}{$Part}
15033 and not $TName_Tid{2}{$Part})
15034 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015035 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015036 if($Param_Pos ne ""
15037 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015038 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 }
15040 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015041 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015042 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015043 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015044 }
15045 $Part_Styled=~s/,(\w)/, $1/g;
15046 push(@Parts, $Part_Styled);
15047 }
15048 if(@Parts)
15049 {
15050 foreach my $Num (0 .. $#Parts)
15051 {
15052 if($Num==$#Parts)
15053 { # add ")" to the last parameter
15054 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15055 }
15056 elsif(length($Parts[$Num])<=45) {
15057 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15058 }
15059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015060 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015061 }
15062 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015063 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015064 }
15065 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015066 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015068 $Signature=~s!\[\]![&#160;]!g;
15069 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015070 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15071 if($SymbolVersion) {
15072 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15073 }
15074 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015075}
15076
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015077sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015078{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015079 my $Signature = $_[0];
15080 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15081 {
15082 $Signature=~s/\A\Q$ShortName\E\(//g;
15083 cut_f_attrs($Signature);
15084 $Signature=~s/\)\Z//;
15085 return ($ShortName, $Signature);
15086 }
15087
15088 # error
15089 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090}
15091
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015092sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015094 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015095 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015096 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15097 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015098 foreach my $Pos (0 .. length($Params) - 1)
15099 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015100 my $S = substr($Params, $Pos, 1);
15101 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015102 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015103 }
15104 if($S eq "," and
15105 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015106 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015107 if($Comma)
15108 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015109 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015110 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015111 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015112 }
15113 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015114 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015115 }
15116 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015117 if(not $Sp)
15118 { # remove spaces
15119 foreach (@Parts)
15120 {
15121 s/\A //g;
15122 s/ \Z//g;
15123 }
15124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015125 return @Parts;
15126}
15127
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015128sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015129{
15130 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015131 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015132 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015133 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15134 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015135 $Center+=length($1);
15136 }
15137 foreach my $Pos (0 .. length($Sign)-1)
15138 {
15139 my $S = substr($Sign, $Pos, 1);
15140 if($S eq $Target)
15141 {
15142 if($B{"("}==$B{")"}
15143 and $B{"<"}==$B{">"}) {
15144 return $Center;
15145 }
15146 }
15147 if(defined $B{$S}) {
15148 $B{$S}+=1;
15149 }
15150 $Center+=1;
15151 }
15152 return 0;
15153}
15154
15155sub appendFile($$)
15156{
15157 my ($Path, $Content) = @_;
15158 return if(not $Path);
15159 if(my $Dir = get_dirname($Path)) {
15160 mkpath($Dir);
15161 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015162 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 print FILE $Content;
15164 close(FILE);
15165}
15166
15167sub writeFile($$)
15168{
15169 my ($Path, $Content) = @_;
15170 return if(not $Path);
15171 if(my $Dir = get_dirname($Path)) {
15172 mkpath($Dir);
15173 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015174 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015175 print FILE $Content;
15176 close(FILE);
15177}
15178
15179sub readFile($)
15180{
15181 my $Path = $_[0];
15182 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015183 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015184 local $/ = undef;
15185 my $Content = <FILE>;
15186 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015187 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015188 $Content=~s/\r/\n/g;
15189 }
15190 return $Content;
15191}
15192
15193sub get_filename($)
15194{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015195 if(defined $Cache{"get_filename"}{$_[0]}) {
15196 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015198 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15199 return ($Cache{"get_filename"}{$_[0]}=$1);
15200 }
15201 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202}
15203
15204sub get_dirname($)
15205{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015206 if(defined $Cache{"get_dirname"}{$_[0]}) {
15207 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015208 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015209 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15210 return ($Cache{"get_dirname"}{$_[0]}=$1);
15211 }
15212 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015213}
15214
15215sub separate_path($) {
15216 return (get_dirname($_[0]), get_filename($_[0]));
15217}
15218
15219sub esc($)
15220{
15221 my $Str = $_[0];
15222 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15223 return $Str;
15224}
15225
15226sub readLineNum($$)
15227{
15228 my ($Path, $Num) = @_;
15229 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015230 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 foreach (1 ... $Num) {
15232 <FILE>;
15233 }
15234 my $Line = <FILE>;
15235 close(FILE);
15236 return $Line;
15237}
15238
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015239sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015241 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 return () if(not $Path or not -f $Path);
15243 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015244 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15245 {
15246 foreach my $AttrVal (split(/;/, $1))
15247 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248 if($AttrVal=~/(.+):(.+)/)
15249 {
15250 my ($Name, $Value) = ($1, $2);
15251 $Attributes{$Name} = $Value;
15252 }
15253 }
15254 }
15255 return \%Attributes;
15256}
15257
15258sub is_abs($) {
15259 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15260}
15261
15262sub get_abs_path($)
15263{ # abs_path() should NOT be called for absolute inputs
15264 # because it can change them
15265 my $Path = $_[0];
15266 if(not is_abs($Path)) {
15267 $Path = abs_path($Path);
15268 }
15269 return $Path;
15270}
15271
15272sub get_OSgroup()
15273{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015274 my $N = $Config{"osname"};
15275 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 return "macos";
15277 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015278 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015279 return "bsd";
15280 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015281 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282 return "beos";
15283 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015284 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015285 return "symbian";
15286 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015287 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 return "windows";
15289 }
15290 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015291 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015292 }
15293}
15294
15295sub getGccVersion($)
15296{
15297 my $LibVersion = $_[0];
15298 if($GCC_VERSION{$LibVersion})
15299 { # dump version
15300 return $GCC_VERSION{$LibVersion};
15301 }
15302 elsif($UsedDump{$LibVersion}{"V"})
15303 { # old-version dumps
15304 return "unknown";
15305 }
15306 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15307 if(not $GccVersion) {
15308 return "unknown";
15309 }
15310 return $GccVersion;
15311}
15312
15313sub showArch($)
15314{
15315 my $Arch = $_[0];
15316 if($Arch eq "arm"
15317 or $Arch eq "mips") {
15318 return uc($Arch);
15319 }
15320 return $Arch;
15321}
15322
15323sub getArch($)
15324{
15325 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015326
15327 if($TargetArch) {
15328 return $TargetArch;
15329 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015330 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015331 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015332 return $CPU_ARCH{$LibVersion};
15333 }
15334 elsif($UsedDump{$LibVersion}{"V"})
15335 { # old-version dumps
15336 return "unknown";
15337 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015338
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015339 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340}
15341
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015342sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015343{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015344 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015346 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015347 if(getArch(1) ne getArch(2)
15348 or getArch(1) eq "unknown"
15349 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015350 { # don't show architecture in the header
15351 $ArchInfo="";
15352 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015353 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015354 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015355 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015356 }
15357 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015358 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015359 }
15360 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015361 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015362 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015363
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015364 my $V1 = $Descriptor{1}{"Version"};
15365 my $V2 = $Descriptor{2}{"Version"};
15366
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015367 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15368 {
15369 my $M1 = $UsedDump{1}{"M"};
15370 my $M2 = $UsedDump{2}{"M"};
15371
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015372 my $M1S = $M1;
15373 my $M2S = $M2;
15374
15375 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15376 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15377
15378 if($M1S eq $M2S
15379 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015380 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015381 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15382 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015383 }
15384 else
15385 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015386 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15387 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015388 }
15389 }
15390 else
15391 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015392 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015393 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015394 }
15395
15396 $Title .= $ArchInfo;
15397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015399 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015400 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015401 $Title = "<h1>".$Title."</h1>\n";
15402 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403}
15404
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015405sub get_CheckedHeaders($)
15406{
15407 my $LibVersion = $_[0];
15408
15409 my @Headers = ();
15410
15411 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15412 {
15413 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015414
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015415 if(not is_target_header($File, $LibVersion)) {
15416 next;
15417 }
15418
15419 if(skipHeader($File, $LibVersion)) {
15420 next;
15421 }
15422
15423 push(@Headers, $Path);
15424 }
15425
15426 return @Headers;
15427}
15428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015429sub get_SourceInfo()
15430{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015431 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015432
15433 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015434 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015435 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15436 $CheckedHeaders .= "<div class='h_list'>\n";
15437 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 +040015438 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015439 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15440 my $Name = get_filename($Identity);
15441 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15442 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015443 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015444 $CheckedHeaders .= "</div>\n";
15445 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015446 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015447
15448 if(my @Sources = keys(%{$Registered_Sources{1}}))
15449 {
15450 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15451 $CheckedSources .= "<div class='h_list'>\n";
15452 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15453 {
15454 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15455 my $Name = get_filename($Identity);
15456 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15457 $CheckedSources .= $Name.$Comment."<br/>\n";
15458 }
15459 $CheckedSources .= "</div>\n";
15460 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15461 }
15462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015463 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015464 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015465 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015466 $CheckedLibs .= "<div class='lib_list'>\n";
15467 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15468 {
15469 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15470 $CheckedLibs .= $Library."<br/>\n";
15471 }
15472 $CheckedLibs .= "</div>\n";
15473 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015474 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015475
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015476 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15477}
15478
15479sub get_ObjTitle()
15480{
15481 if(defined $UsedDump{1}{"DWARF"}) {
15482 return "Objects";
15483 }
15484 else {
15485 return ucfirst($SLIB_TYPE)." Libraries";
15486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015487}
15488
15489sub get_TypeProblems_Count($$$)
15490{
15491 my ($TypeChanges, $TargetPriority, $Level) = @_;
15492 my $Type_Problems_Count = 0;
15493 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15494 {
15495 my %Kinds_Target = ();
15496 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15497 {
15498 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15499 {
15500 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015501 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15502 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015503 if($Kinds_Target{$Kind}{$Target}) {
15504 next;
15505 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015506
15507 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15508 {
15509 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15510 { # select a problem with the highest priority
15511 next;
15512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513 }
15514 $Kinds_Target{$Kind}{$Target} = 1;
15515 $Type_Problems_Count += 1;
15516 }
15517 }
15518 }
15519 return $Type_Problems_Count;
15520}
15521
15522sub get_Summary($)
15523{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015524 my $Level = $_[0];
15525 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015526 $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 +040015527 %{$RESULT{$Level}} = (
15528 "Problems"=>0,
15529 "Warnings"=>0,
15530 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015531 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015532 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015533 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015534 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 {
15536 if(not defined $CompatRules{$Level}{$Kind})
15537 { # unknown rule
15538 if(not $UnknownRules{$Level}{$Kind})
15539 { # only one warning
15540 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15541 $UnknownRules{$Level}{$Kind}=1;
15542 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015543 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015544 }
15545 }
15546 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015547 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15548 {
15549 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15550 {
15551 if(not defined $CompatRules{$Level}{$Kind})
15552 { # unknown rule
15553 if(not $UnknownRules{$Level}{$Kind})
15554 { # only one warning
15555 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15556 $UnknownRules{$Level}{$Kind}=1;
15557 }
15558 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15559 }
15560 }
15561 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015562 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015563 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015564 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015565 {
15566 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15567 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015568 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015569 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015570 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015571 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015572 $Added += 1;
15573 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015574 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015575 {
15576 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015577 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015578 }
15579 else
15580 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015581 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015582 $I_Other += 1;
15583 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015584 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585 $I_Problems_High += 1;
15586 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015587 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015588 $I_Problems_Medium += 1;
15589 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015590 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015591 $I_Problems_Low += 1;
15592 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015593 if(($Severity ne "Low" or $StrictCompat)
15594 and $Severity ne "Safe") {
15595 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596 }
15597 }
15598 }
15599 }
15600 }
15601 }
15602 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015603 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015605 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015606 {
15607 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15608 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015609 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015611 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15612 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015613 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015614 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15615
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015616 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015617 { # select a problem with the highest priority
15618 next;
15619 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015620
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015621 if(($Severity ne "Low" or $StrictCompat)
15622 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015623 {
15624 if(defined $TotalAffected{$Level}{$Interface})
15625 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015626 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15627 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015628 }
15629 }
15630 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015631 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015633 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015634
15635 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15636
15637 if($MaxSeverity)
15638 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015639 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15640 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015641 }
15642 }
15643 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015644 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015646 }
15647 }
15648 }
15649 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015650
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015651 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15652 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15653 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15654 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015655
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015656 %TypeChanges = (); # free memory
15657
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015658 # changed and removed public symbols
15659 my $SCount = keys(%{$CheckedSymbols{$Level}});
15660 if($ExtendedCheck)
15661 { # don't count external_func_0 for constants
15662 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015663 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015664 if($SCount)
15665 {
15666 my %Weight = (
15667 "High" => 100,
15668 "Medium" => 50,
15669 "Low" => 25
15670 );
15671 foreach (keys(%{$TotalAffected{$Level}})) {
15672 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015674 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015676 else {
15677 $RESULT{$Level}{"Affected"} = 0;
15678 }
15679
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015680 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15681 if($RESULT{$Level}{"Affected"}>=100) {
15682 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015683 }
15684
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015685 $RESULT{$Level}{"Problems"} += $Removed;
15686 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015687 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015688 if($StrictCompat) {
15689 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15690 }
15691 else {
15692 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015695 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015696 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015697 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015698 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015699 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015700 if($Severity eq "Safe")
15701 {
15702 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015703 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015704 elsif($Severity eq "Low")
15705 {
15706 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015708 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015709 }
15710
15711 if($C_Problems_Low)
15712 {
15713 if($StrictCompat) {
15714 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15715 }
15716 else {
15717 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015718 }
15719 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015720 if($RESULT{$Level}{"Problems"}
15721 and $RESULT{$Level}{"Affected"}) {
15722 $RESULT{$Level}{"Verdict"} = "incompatible";
15723 }
15724 else {
15725 $RESULT{$Level}{"Verdict"} = "compatible";
15726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015727
15728 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15729 if(not $TotalTypes)
15730 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015731 $TotalTypes = keys(%{$TName_Tid{1}});
15732 }
15733
15734 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15735 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15736
15737 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15738
15739 if($ReportFormat eq "xml")
15740 { # XML
15741 # test info
15742 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15743 $TestInfo .= " <version1>\n";
15744 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015745 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015746 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15747 $TestInfo .= " </version1>\n";
15748
15749 $TestInfo .= " <version2>\n";
15750 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015751 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15753 $TestInfo .= " </version2>\n";
15754 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15755
15756 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015757 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015758 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015759 $TestResults .= " <headers>\n";
15760 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15761 {
15762 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15763 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15764 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15765 }
15766 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015767 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015768
15769 if(my @Sources = keys(%{$Registered_Sources{1}}))
15770 {
15771 $TestResults .= " <sources>\n";
15772 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15773 {
15774 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15775 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15776 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15777 }
15778 $TestResults .= " </sources>\n";
15779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780
15781 $TestResults .= " <libs>\n";
15782 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15783 {
15784 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15785 $TestResults .= " <name>$Library</name>\n";
15786 }
15787 $TestResults .= " </libs>\n";
15788
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015789 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015790 $TestResults .= " <types>".$TotalTypes."</types>\n";
15791
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015792 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15793 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015794 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15795
15796 # problem summary
15797 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15798 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15799
15800 $Problem_Summary .= " <problems_with_types>\n";
15801 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15802 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15803 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15804 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15805 $Problem_Summary .= " </problems_with_types>\n";
15806
15807 $Problem_Summary .= " <problems_with_symbols>\n";
15808 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15809 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15810 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015811 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015812 $Problem_Summary .= " </problems_with_symbols>\n";
15813
15814 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015815 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015816 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015817
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015818 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15819
15820 return ($TestInfo.$TestResults.$Problem_Summary, "");
15821 }
15822 else
15823 { # HTML
15824 # test info
15825 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015826 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015827
15828 if($TargetComponent eq "library") {
15829 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
15830 }
15831 else {
15832 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
15833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015834
15835 my (@VInf1, @VInf2, $AddTestInfo) = ();
15836 if($Arch1 ne "unknown"
15837 and $Arch2 ne "unknown")
15838 { # CPU arch
15839 if($Arch1 eq $Arch2)
15840 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015841 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015842 }
15843 else
15844 { # go to the version number
15845 push(@VInf1, showArch($Arch1));
15846 push(@VInf2, showArch($Arch2));
15847 }
15848 }
15849 if($GccV1 ne "unknown"
15850 and $GccV2 ne "unknown"
15851 and $OStarget ne "windows")
15852 { # GCC version
15853 if($GccV1 eq $GccV2)
15854 { # go to the separate section
15855 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15856 }
15857 else
15858 { # go to the version number
15859 push(@VInf1, "gcc ".$GccV1);
15860 push(@VInf2, "gcc ".$GccV2);
15861 }
15862 }
15863 # show long version names with GCC version and CPU architecture name (if different)
15864 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15865 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15866 $TestInfo .= $AddTestInfo;
15867 #if($COMMON_LANGUAGE{1}) {
15868 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15869 #}
15870 if($ExtendedCheck) {
15871 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015873 if($JoinReport)
15874 {
15875 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015876 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015877 }
15878 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015879 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015880 }
15881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882 $TestInfo .= "</table>\n";
15883
15884 # test results
15885 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015887
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015888 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015889 {
15890 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15891 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15892 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015893
15894 if(my @Sources = keys(%{$Registered_Sources{1}}))
15895 {
15896 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15897 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015899
15900 if(not $ExtendedCheck)
15901 {
15902 my $Libs_Link = "0";
15903 $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 +040015904 $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 +040015905 }
15906
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015907 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015908
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015909 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015910 if($JoinReport) {
15911 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15912 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015913 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015914 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015915 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15916 }
15917 else {
15918 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15919 }
15920 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015921 $TestResults .= "</table>\n";
15922
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015923 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015924 # problem summary
15925 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015926 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015927 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15928
15929 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015930 if($Added>0)
15931 {
15932 if($JoinReport) {
15933 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15934 }
15935 else {
15936 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15937 }
15938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015939 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015940 $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 +040015941
15942 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015943 if($Removed>0)
15944 {
15945 if($JoinReport) {
15946 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15947 }
15948 else {
15949 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15950 }
15951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015953 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15954 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955
15956 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015957 $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 +040015958 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015959 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15960 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015961
15962 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015963 $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 +040015964 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015965 $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 +040015966
15967 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015968 $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 +040015969 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015970 $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 +040015971
15972 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015973 $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 +040015974 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015975 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15976 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015977
15978 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015979 $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 +040015980 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015981 $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 +040015982
15983 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015984 $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 +040015985 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015986 $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 +040015987
15988 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015989 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15990 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015991 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015992 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015993 $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 +040015994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015995 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015996 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015997 {
15998 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015999 $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 Ponomarenko1fbbce62015-10-13 00:08:59 +030016000 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016002
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016003 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016004 {
16005 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016006 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016007 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016009
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016010 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016011 {
16012 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16013 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016014 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016015 }
16016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016017 $META_DATA .= "tool_version:$TOOL_VERSION";
16018 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016019 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016020 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16021 }
16022}
16023
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016024sub getStyle($$$)
16025{
16026 my ($Subj, $Act, $Num) = @_;
16027 my %Style = (
16028 "A"=>"new",
16029 "R"=>"failed",
16030 "S"=>"passed",
16031 "L"=>"warning",
16032 "M"=>"failed",
16033 "H"=>"failed"
16034 );
16035 if($Num>0) {
16036 return " class='".$Style{$Act}."'";
16037 }
16038 return "";
16039}
16040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016041sub show_number($)
16042{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016043 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016044 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016045 my $Num = cut_off_number($_[0], 2, 0);
16046 if($Num eq "0")
16047 {
16048 foreach my $P (3 .. 7)
16049 {
16050 $Num = cut_off_number($_[0], $P, 1);
16051 if($Num ne "0") {
16052 last;
16053 }
16054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016055 }
16056 if($Num eq "0") {
16057 $Num = $_[0];
16058 }
16059 return $Num;
16060 }
16061 return $_[0];
16062}
16063
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016064sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016065{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016066 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016067 if($num!~/\./)
16068 {
16069 $num .= ".";
16070 foreach (1 .. $digs_to_cut-1) {
16071 $num .= "0";
16072 }
16073 }
16074 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16075 {
16076 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16077 $num .= "0";
16078 }
16079 }
16080 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16081 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16082 }
16083 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016084 if($z) {
16085 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016087 return $num;
16088}
16089
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016090sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016091{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016092 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016093 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016094
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016095 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016096 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16097 {
16098 my $Header = $Constants{1}{$Constant}{"Header"};
16099 if(not $Header)
16100 { # added
16101 $Header = $Constants{2}{$Constant}{"Header"}
16102 }
16103
16104 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16105 {
16106 if(not defined $CompatRules{$Level}{$Kind}) {
16107 next;
16108 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016109 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016110 next;
16111 }
16112 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016114 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016115
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016116 if($ReportFormat eq "xml")
16117 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016118 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016119 {
16120 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016121 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016122 {
16123 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016124 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16125 {
16126 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16127 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16128 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016129
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016130 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16131 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16132 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016133 if($Overcome) {
16134 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16135 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016136 $CHANGED_CONSTANTS .= " </problem>\n";
16137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016138 $CHANGED_CONSTANTS .= " </constant>\n";
16139 }
16140 $CHANGED_CONSTANTS .= " </header>\n";
16141 }
16142 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16143 }
16144 else
16145 { # HTML
16146 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016147 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016148 {
16149 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016150 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016152 my $Report = "";
16153
16154 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16155 {
16156 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16157 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016158 $Report .= "<tr>\n<th>1</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>$Effect</td>\n</tr>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016159 $Number += 1;
16160 }
16161 if($Report)
16162 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016163 $Report = $ContentDivStart."<table class='ptable'>\n<tr>\n<th width='2%'></th>\n<th width='47%'>Change</th>\n<th>Effect</th>\n</tr>\n".$Report."</table>\n<br/>\n$ContentDivEnd\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016164 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16165 $Report = insertIDs($Report);
16166 }
16167 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016168 }
16169 $CHANGED_CONSTANTS .= "<br/>\n";
16170 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016171 if($CHANGED_CONSTANTS)
16172 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016173 my $Title = "Problems with Constants, $TargetSeverity Severity";
16174 if($TargetSeverity eq "Safe")
16175 { # Safe Changes
16176 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016177 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016178 $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 +040016179 }
16180 }
16181 return $CHANGED_CONSTANTS;
16182}
16183
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184sub getTitle($$$)
16185{
16186 my ($Header, $Library, $NameSpace) = @_;
16187 my $Title = "";
16188 if($Library and $Library!~/\.\w+\Z/) {
16189 $Library .= " (.$LIB_EXT)";
16190 }
16191 if($Header and $Library)
16192 {
16193 $Title .= "<span class='h_name'>$Header</span>";
16194 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16195 }
16196 elsif($Library) {
16197 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16198 }
16199 elsif($Header) {
16200 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16201 }
16202 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016203 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016204 }
16205 return $Title;
16206}
16207
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016208sub get_Report_Added($)
16209{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016210 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016211 my $ADDED_INTERFACES = "";
16212 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016213 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016214 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218 {
16219 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16220 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 if($Level eq "Source" and $ReportFormat eq "html")
16222 { # do not show library name in HTML report
16223 $DyLib = "";
16224 }
16225 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016226 }
16227 }
16228 }
16229 if($ReportFormat eq "xml")
16230 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016231 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016232 {
16233 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016234 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016235 {
16236 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016237 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016238 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16239 }
16240 $ADDED_INTERFACES .= " </library>\n";
16241 }
16242 $ADDED_INTERFACES .= " </header>\n";
16243 }
16244 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16245 }
16246 else
16247 { # HTML
16248 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016249 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016250 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016253 my %NameSpaceSymbols = ();
16254 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016255 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016257 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016259 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16260 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261 foreach my $Interface (@SortedInterfaces)
16262 {
16263 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016264 my $Signature = get_Signature($Interface, 2);
16265 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016266 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016268 if($Interface=~/\A(_Z|\?)/)
16269 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016270 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016271 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>\n<br/>\n<br/>\n".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 }
16273 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016274 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 }
16276 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016277 else
16278 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016280 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016281 }
16282 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016283 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 }
16285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016287 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289 }
16290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 if($ADDED_INTERFACES)
16292 {
16293 my $Anchor = "<a name='Added'></a>";
16294 if($JoinReport) {
16295 $Anchor = "<a name='".$Level."_Added'></a>";
16296 }
16297 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016298 }
16299 }
16300 return $ADDED_INTERFACES;
16301}
16302
16303sub get_Report_Removed($)
16304{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016305 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016306 my $REMOVED_INTERFACES = "";
16307 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016308 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016309 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016310 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016312 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016313 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016314 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16315 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016316 if($Level eq "Source" and $ReportFormat eq "html")
16317 { # do not show library name in HTML report
16318 $DyLib = "";
16319 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016320 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016321 }
16322 }
16323 }
16324 if($ReportFormat eq "xml")
16325 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016326 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327 {
16328 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016329 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 {
16331 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016332 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16333 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016334 }
16335 $REMOVED_INTERFACES .= " </library>\n";
16336 }
16337 $REMOVED_INTERFACES .= " </header>\n";
16338 }
16339 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16340 }
16341 else
16342 { # HTML
16343 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016344 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016348 my %NameSpaceSymbols = ();
16349 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016350 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016352 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016353 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016354 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16355 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016356 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016357 {
16358 $Removed_Number += 1;
16359 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016360 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016362 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016363 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016364 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016365 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016367 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span>\n<br/>\n<br/>\n".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 }
16369 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016370 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371 }
16372 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016373 else
16374 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016376 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377 }
16378 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016379 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 }
16381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016382 }
16383 }
16384 $REMOVED_INTERFACES .= "<br/>\n";
16385 }
16386 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016387 if($REMOVED_INTERFACES)
16388 {
16389 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16390 if($JoinReport) {
16391 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16392 }
16393 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 }
16395 }
16396 return $REMOVED_INTERFACES;
16397}
16398
16399sub getXmlParams($$)
16400{
16401 my ($Content, $Problem) = @_;
16402 return "" if(not $Content or not $Problem);
16403 my %XMLparams = ();
16404 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16405 {
16406 my $Macro = "\@".lc($Attr);
16407 if($Content=~/\Q$Macro\E/) {
16408 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16409 }
16410 }
16411 my @PString = ();
16412 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016413 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016414 }
16415 if(@PString) {
16416 return " ".join(" ", @PString);
16417 }
16418 else {
16419 return "";
16420 }
16421}
16422
16423sub addMarkup($)
16424{
16425 my $Content = $_[0];
16426 # auto-markup
16427 $Content=~s/\n[ ]*//; # spaces
16428 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16429 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016430 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016431 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16432 if($Content=~/\ANOTE:/)
16433 { # notes
16434 $Content=~s!(NOTE):!<b>$1</b>:!g;
16435 }
16436 else {
16437 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16438 }
16439 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16440 my @Keywords = (
16441 "void",
16442 "const",
16443 "static",
16444 "restrict",
16445 "volatile",
16446 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016447 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016448 );
16449 my $MKeys = join("|", @Keywords);
16450 foreach (@Keywords) {
16451 $MKeys .= "|non-".$_;
16452 }
16453 $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 +040016454
16455 # Markdown
16456 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16457 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 return $Content;
16459}
16460
16461sub applyMacroses($$$$)
16462{
16463 my ($Level, $Kind, $Content, $Problem) = @_;
16464 return "" if(not $Content or not $Problem);
16465 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16466 $Content = addMarkup($Content);
16467 # macros
16468 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16469 {
16470 my $Macro = "\@".lc($Attr);
16471 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016472 if(not defined $Value
16473 or $Value eq "") {
16474 next;
16475 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016476
16477 if(index($Content, $Macro)==-1) {
16478 next;
16479 }
16480
16481 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16482 and $Kind!~/_Type_/
16483 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016485 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016486 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 $Value = black_name($Value);
16488 }
16489 elsif($Value=~/\s/) {
16490 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16491 }
16492 elsif($Value=~/\A\d+\Z/
16493 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16494 { # bits to bytes
16495 if($Value % $BYTE_SIZE)
16496 { # bits
16497 if($Value==1) {
16498 $Value = "<b>".$Value."</b> bit";
16499 }
16500 else {
16501 $Value = "<b>".$Value."</b> bits";
16502 }
16503 }
16504 else
16505 { # bytes
16506 $Value /= $BYTE_SIZE;
16507 if($Value==1) {
16508 $Value = "<b>".$Value."</b> byte";
16509 }
16510 else {
16511 $Value = "<b>".$Value."</b> bytes";
16512 }
16513 }
16514 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016515 else
16516 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016517 $Value = "<b>".htmlSpecChars($Value)."</b>";
16518 }
16519 $Content=~s/\Q$Macro\E/$Value/g;
16520 }
16521
16522 if($Content=~/(\A|[^\@\w])\@\w/)
16523 {
16524 if(not $IncompleteRules{$Level}{$Kind})
16525 { # only one warning
16526 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16527 $IncompleteRules{$Level}{$Kind} = 1;
16528 }
16529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016530 return $Content;
16531}
16532
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016533sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016534{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016535 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016536 my $INTERFACE_PROBLEMS = "";
16537 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016538
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16542 if($SV and defined $CompatProblems{$Level}{$SN}) {
16543 next;
16544 }
16545 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016546 {
16547 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016549 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016550 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16551 my $DyLib = $Symbol_Library{1}{$Symbol};
16552 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016553 { # Symbol with Version
16554 $DyLib = $Symbol_Library{1}{$VSym};
16555 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016556 if(not $DyLib)
16557 { # const global data
16558 $DyLib = "";
16559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016560 if($Level eq "Source" and $ReportFormat eq "html")
16561 { # do not show library name in HTML report
16562 $DyLib = "";
16563 }
16564 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16565 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016566 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016567 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16568 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016569 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016570 }
16571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016572 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16573 {
16574 delete($SymbolChanges{$Symbol}{$Kind});
16575 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 }
16579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 if(not keys(%{$SymbolChanges{$Symbol}})) {
16581 delete($SymbolChanges{$Symbol});
16582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016583 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016585 if($ReportFormat eq "xml")
16586 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016587 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 {
16589 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016590 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 {
16592 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016593 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16594 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 {
16596 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16597 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16598 {
16599 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16600 {
16601 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016602 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016603
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16605 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16606 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16607 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16608 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016609 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16610 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16611 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016612 $INTERFACE_PROBLEMS .= " </problem>\n";
16613 }
16614 }
16615 $INTERFACE_PROBLEMS .= " </symbol>\n";
16616 }
16617 $INTERFACE_PROBLEMS .= " </library>\n";
16618 }
16619 $INTERFACE_PROBLEMS .= " </header>\n";
16620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016621 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 }
16623 else
16624 { # HTML
16625 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016626 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016628 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016630 my (%NameSpaceSymbols, %NewSignature) = ();
16631 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016632 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016636 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016637 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 +040016638 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 my $Signature = get_Signature($Symbol, 1);
16641 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016643 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016645 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016648 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016651 }
16652 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16653 {
16654 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016655 $SYMBOL_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>".$Effect."</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016656 $ProblemNum += 1;
16657 $ProblemsNum += 1;
16658 }
16659 }
16660 }
16661 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016663 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016664 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016666 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 }
16668 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016669 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016671 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16672 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16673 if($NewSignature{$Symbol})
16674 { # argument list changed to
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016675 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span>\n<br/>\n<span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 if($Symbol=~/\A(_Z|\?)/) {
16678 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16679 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016680 $INTERFACE_PROBLEMS .= "<table class='ptable'>\n<tr>\n<th width='2%'></th>\n<th width='47%'>Change</th>\n<th>Effect</th>\n</tr>\n$SYMBOL_REPORT</table>\n<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016683 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016684 }
16685 }
16686 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016687 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016688 }
16689 }
16690 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 if($INTERFACE_PROBLEMS)
16693 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016694 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16695 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16696 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016697 { # Safe Changes
16698 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016700 $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 +040016701 }
16702 }
16703 return $INTERFACE_PROBLEMS;
16704}
16705
16706sub get_Report_TypeProblems($$)
16707{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016708 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016709 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016710 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016711
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016712 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016714 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016715 {
16716 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16717 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016718 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016719 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016720 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016721 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016722 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016723
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016724 if($Severity eq "Safe"
16725 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 next;
16727 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016729 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16730 {
16731 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16732 { # select a problem with the highest priority
16733 next;
16734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016735 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016736
16737 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016738 }
16739 }
16740 }
16741 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016742
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016743 my %Kinds_Locations = ();
16744 foreach my $TypeName (keys(%TypeChanges))
16745 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016746 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016747 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16748 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016749 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016751 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016752 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 { # other priority
16754 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16755 next;
16756 }
16757 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16758 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016759 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016760 { # duplicate target
16761 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16762 next;
16763 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016764 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016765 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016766 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 }
16768 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16769 delete($TypeChanges{$TypeName}{$Kind});
16770 }
16771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016772 if(not keys(%{$TypeChanges{$TypeName}})) {
16773 delete($TypeChanges{$TypeName});
16774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016775 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016776
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016777 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 +040016778 if($ReportFormat eq "xml")
16779 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016780 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016781 {
16782 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016783 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016785 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016786 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16787 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016788 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016789 {
16790 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16791 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16792 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16793 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16794 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16795 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016796 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16797 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 $TYPE_PROBLEMS .= " </problem>\n";
16800 }
16801 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016802 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016803 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016804 $TYPE_PROBLEMS .= showVTables($TypeName);
16805 }
16806 $TYPE_PROBLEMS .= " </type>\n";
16807 }
16808 $TYPE_PROBLEMS .= " </header>\n";
16809 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 }
16812 else
16813 { # HTML
16814 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016815 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016817 my (%NameSpace_Type) = ();
16818 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016819 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016820 }
16821 foreach my $NameSpace (sort keys(%NameSpace_Type))
16822 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016824 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 +040016825 foreach my $TypeName (@SortedTypes)
16826 {
16827 my $ProblemNum = 1;
16828 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016829
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16831 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016832 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016833 {
16834 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16835 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16836 {
16837 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016838 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>$Effect</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016839 $ProblemNum += 1;
16840 $ProblemsNum += 1;
16841 }
16842 }
16843 }
16844 $ProblemNum -= 1;
16845 if($TYPE_REPORT)
16846 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016847 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016848 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016849 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016850 $ShowVTables = showVTables($TypeName);
16851 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016852
16853 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016854 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16855 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16856 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16857 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016858 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016859 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016860 }
16861 }
16862 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016863 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 }
16865 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016866
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016867 if($TYPE_PROBLEMS)
16868 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16870 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016871 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 { # Safe Changes
16873 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016875 $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 +040016876 }
16877 }
16878 return $TYPE_PROBLEMS;
16879}
16880
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016881sub show_Type($$$)
16882{
16883 my ($Name, $Html, $LibVersion) = @_;
16884 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16885 $TType = lc($TType);
16886 if($TType=~/struct|union|enum/) {
16887 $Name=~s/\A\Q$TType\E //g;
16888 }
16889 if($Html) {
16890 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16891 }
16892 else {
16893 $Name = $TType." ".$Name;
16894 }
16895 return $Name;
16896}
16897
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898sub get_Anchor($$$)
16899{
16900 my ($Kind, $Level, $Severity) = @_;
16901 if($JoinReport)
16902 {
16903 if($Severity eq "Safe") {
16904 return "Other_".$Level."_Changes_In_".$Kind."s";
16905 }
16906 else {
16907 return $Kind."_".$Level."_Problems_".$Severity;
16908 }
16909 }
16910 else
16911 {
16912 if($Severity eq "Safe") {
16913 return "Other_Changes_In_".$Kind."s";
16914 }
16915 else {
16916 return $Kind."_Problems_".$Severity;
16917 }
16918 }
16919}
16920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016921sub showVTables($)
16922{
16923 my $TypeName = $_[0];
16924 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016925 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 if(defined $Type1{"VTable"}
16927 and keys(%{$Type1{"VTable"}}))
16928 {
16929 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016930 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 if(defined $Type2{"VTable"}
16932 and keys(%{$Type2{"VTable"}}))
16933 {
16934 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16935 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016938 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16939 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 }
16941 my $VTABLES = "";
16942 if($ReportFormat eq "xml")
16943 { # XML
16944 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016945 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016947 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016948 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16949 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 $VTABLES .= " </entry>\n";
16951 }
16952 $VTABLES .= " </vtable>\n\n";
16953 }
16954 else
16955 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016956 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016957 $VTABLES .= "<tr><th>Offset</th>";
16958 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016959 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016960 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 {
16962 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016963 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016965 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016966 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016967 $Color1 = " class='failed'";
16968 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 }
16970 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016971 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 }
16973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016974 $VTABLES .= "<tr><th>".$Index."</th>\n";
16975 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16976 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 }
16978 $VTABLES .= "</table><br/>\n";
16979 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 }
16982 return $VTABLES;
16983 }
16984 }
16985 return "";
16986}
16987
16988sub simpleVEntry($)
16989{
16990 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016991 if(not defined $VEntry
16992 or $VEntry eq "") {
16993 return "";
16994 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016995
16996 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016997 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16998 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16999 if($VEntry=~/\A_ZThn.+\Z/) {
17000 $VEntry = "non-virtual thunk";
17001 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017002 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017003 # support for old GCC versions
17004 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17005 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17006 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17008 return $VEntry;
17009}
17010
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017011sub adjustParamPos($$$)
17012{
17013 my ($Pos, $Symbol, $LibVersion) = @_;
17014 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17015 {
17016 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17017 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17018 {
17019 return $Pos-1;
17020 }
17021
17022 return $Pos;
17023 }
17024
17025 return undef;
17026}
17027
17028sub getParamPos($$$)
17029{
17030 my ($Name, $Symbol, $LibVersion) = @_;
17031
17032 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17033 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17034 {
17035 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17036 foreach (keys(%{$Info->{"Param"}}))
17037 {
17038 if($Info->{"Param"}{$_}{"name"} eq $Name)
17039 {
17040 return $_;
17041 }
17042 }
17043 }
17044
17045 return undef;
17046}
17047
17048sub getParamName($)
17049{
17050 my $Loc = $_[0];
17051 $Loc=~s/\->.*//g;
17052 return $Loc;
17053}
17054
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017055sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017056{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017057 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017058 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017059
17060 if(defined $AffectLimit)
17061 {
17062 $LIMIT = $AffectLimit;
17063 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017064
17065 my %SymSel = ();
17066 my %SymLocKind = ();
17067
17068 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017070 if(index($Symbol, "_Z")==0
17071 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072 { # duplicated problems for C2 constructors, D2 and D0 destructors
17073 next;
17074 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017075
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017076 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017078 if(not defined $CompatProblems{$Level}{$Symbol}
17079 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17080 next;
17081 }
17082
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017083 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017085 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017086 next;
17087 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017088
17089 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17090 if($Level eq "Source")
17091 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017092 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017093 }
17094
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017095 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017096 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017097 { # duplicated problems for versioned symbols
17098 next;
17099 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017100
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017101 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017102 if($Type_Name ne $Target_TypeName) {
17103 next;
17104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017106 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 }
17108 }
17109 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017110
17111 foreach my $Symbol (sort keys(%SymLocKind))
17112 {
17113 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17114 {
17115 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17116 {
17117 $SymSel{$Symbol}{"Loc"} = $Loc;
17118 $SymSel{$Symbol}{"Kind"} = $Kind;
17119
17120 last LOOP;
17121 }
17122 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017123 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017124
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017126 my $Num = 0;
17127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017128 if($ReportFormat eq "xml")
17129 { # XML
17130 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017131
17132 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017134 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017135 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017136 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017137
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017139 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017140 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017141 $Target .= " param=\"$PName\"";
17142 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017144 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017145 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017146 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017147 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017148 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017149 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017150
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017151 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017152 $Target .= " field=\"$1\"";
17153 }
17154
17155 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017156 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017158
17159 if($Num>$LIMIT) {
17160 last LOOP;
17161 }
17162
17163 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017164 }
17165 $Affected .= " </affected>\n";
17166 }
17167 else
17168 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017169 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017170 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017171 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17172 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017173 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017174 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17175
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017176 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017177 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17178
17179 if($Num>$LIMIT) {
17180 last;
17181 }
17182
17183 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017184 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017185
17186 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017187 $Affected .= " ...\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017188 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017189
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017190 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017191 if($Affected)
17192 {
17193 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017194 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017195 }
17196 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017198 return $Affected;
17199}
17200
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017201sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017202{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017203 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017204 if($L2=~/\A(retval|this)\b/
17205 and $L1!~/\A(retval|this)\b/)
17206 {
17207 if($L1!~/\-\>/) {
17208 return 1;
17209 }
17210 elsif($L2=~/\-\>/) {
17211 return 1;
17212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017213 }
17214 return 0;
17215}
17216
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017217sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017218{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017219 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017220
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017221 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017222
17223 my $Location_I = $Location;
17224 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017226 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228 if($Kind eq "Overridden_Virtual_Method"
17229 or $Kind eq "Overridden_Virtual_Method_B") {
17230 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17231 }
17232 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17233 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017234 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17237 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017238 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17239 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017241 if($ClassName eq $Problem{"Type_Name"}) {
17242 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17243 }
17244 else {
17245 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17246 }
17247 }
17248 else
17249 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017250 my $TypeID = undef;
17251
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017252 if($Location=~/retval/)
17253 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017254 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017255 push(@Sentence, "Field \'".$Location."\' in return value");
17256 }
17257 else {
17258 push(@Sentence, "Return value");
17259 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017260
17261 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017262 }
17263 elsif($Location=~/this/)
17264 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017265 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017266 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17267 }
17268 else {
17269 push(@Sentence, "\'this\' pointer");
17270 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017271
17272 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017273 }
17274 else
17275 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017276
17277 my $PName = getParamName($Location);
17278 my $PPos = getParamPos($PName, $Symbol, 1);
17279
17280 if(index($Location, "->")!=-1) {
17281 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017282 }
17283 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017284 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017285 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017286 if($PName) {
17287 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017288 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017289
17290 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17291 }
17292
17293 if($Location!~/this/)
17294 {
17295 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017296 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017297 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017298 push(@Sentence, "(pointer)");
17299 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017300 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017301 push(@Sentence, "(reference)");
17302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017303 }
17304 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017306 if($Location eq "this") {
17307 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17308 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017309 else
17310 {
17311 my $Location_T = $Location;
17312 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17313
17314 my $TypeID_Problem = $TypeID;
17315 if($Location_T) {
17316 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17317 }
17318
17319 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17320 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17321 }
17322 else {
17323 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017325 }
17326 }
17327 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017328 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017329 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 +040017330 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017331
17332 my $Sent = join(" ", @Sentence);
17333
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017334 $Sent=~s/->/./g;
17335
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017336 if($ReportFormat eq "xml")
17337 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017338 $Sent=~s/'//g;
17339 }
17340
17341 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342}
17343
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017344sub getFieldType($$$)
17345{
17346 my ($Location, $TypeId, $LibVersion) = @_;
17347
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017348 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017349
17350 foreach my $Name (@Fields)
17351 {
17352 my %Info = get_BaseType($TypeId, $LibVersion);
17353
17354 foreach my $Pos (keys(%{$Info{"Memb"}}))
17355 {
17356 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17357 {
17358 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17359 last;
17360 }
17361 }
17362 }
17363
17364 return $TypeId;
17365}
17366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017367sub get_XmlSign($$)
17368{
17369 my ($Symbol, $LibVersion) = @_;
17370 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17371 my $Report = "";
17372 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17373 {
17374 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017375 my $Type = $Info->{"Param"}{$Pos}{"type"};
17376 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017377 foreach my $Typedef (keys(%ChangedTypedef))
17378 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017379 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17380 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017382 }
17383 $Report .= " <param pos=\"$Pos\">\n";
17384 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017385 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017386 $Report .= " </param>\n";
17387 }
17388 if(my $Return = $Info->{"Return"})
17389 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017390 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017392 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 $Report .= " </retval>\n";
17394 }
17395 return $Report;
17396}
17397
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017398sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017399{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017400 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017402 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017403 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017404 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17405 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017406 next;
17407 }
17408 $Report .= " <symbol name=\"$Symbol\">\n";
17409 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017410 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017411 {
17412 if(defined $CompleteSignature{1}{$Symbol}
17413 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17414 {
17415 $P1 = get_XmlSign($Symbol, 1);
17416 $S1 = get_Signature($Symbol, 1);
17417 }
17418 elsif($Symbol=~/\A(_Z|\?)/) {
17419 $S1 = $tr_name{$Symbol};
17420 }
17421 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017422 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017423 {
17424 if(defined $CompleteSignature{2}{$Symbol}
17425 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17426 {
17427 $P2 = get_XmlSign($Symbol, 2);
17428 $S2 = get_Signature($Symbol, 2);
17429 }
17430 elsif($Symbol=~/\A(_Z|\?)/) {
17431 $S2 = $tr_name{$Symbol};
17432 }
17433 }
17434 if($S1)
17435 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017436 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017437 $Report .= $P1;
17438 $Report .= " </old>\n";
17439 }
17440 if($S2 and $S2 ne $S1)
17441 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017442 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017443 $Report .= $P2;
17444 $Report .= " </new>\n";
17445 }
17446 $Report .= " </symbol>\n";
17447 }
17448 $Report .= "</symbols_info>\n";
17449 return $Report;
17450}
17451
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017452sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017453{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017454 my ($Level, $Report) = @_;
17455 if($ReportFormat eq "xml") {
17456 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017457 }
17458 if($StdOut)
17459 { # --stdout option
17460 print STDOUT $Report;
17461 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017462 else
17463 {
17464 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017465 mkpath(get_dirname($RPath));
17466
17467 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17468 print REPORT $Report;
17469 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017470 }
17471}
17472
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017473sub getReport($)
17474{
17475 my $Level = $_[0];
17476 if($ReportFormat eq "xml")
17477 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017478 if($Level eq "Join")
17479 {
17480 my $Report = "<reports>\n";
17481 $Report .= getReport("Binary");
17482 $Report .= getReport("Source");
17483 $Report .= "</reports>\n";
17484 return $Report;
17485 }
17486 else
17487 {
17488 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17489 my ($Summary, $MetaData) = get_Summary($Level);
17490 $Report .= $Summary."\n";
17491 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17492 $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 +040017493
17494 # additional symbols info (if needed)
17495 # $Report .= get_Report_SymbolsInfo($Level);
17496
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017497 $Report .= "</report>\n";
17498 return $Report;
17499 }
17500 }
17501 else
17502 { # HTML
17503 my $CssStyles = readModule("Styles", "Report.css");
17504 my $JScripts = readModule("Scripts", "Sections.js");
17505 if($Level eq "Join")
17506 {
17507 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17508 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017509 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017510 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17511 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 +040017512 my ($BSummary, $BMetaData) = get_Summary("Binary");
17513 my ($SSummary, $SMetaData) = get_Summary("Source");
17514 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 +030017515 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017516 <br/>
17517 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017518 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17519 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017520 </div>";
17521 $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>";
17522 $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 +030017523 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017524 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017525 return $Report;
17526 }
17527 else
17528 {
17529 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017530 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17531 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17532 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 +040017533 if($Level eq "Binary")
17534 {
17535 if(getArch(1) eq getArch(2)
17536 and getArch(1) ne "unknown") {
17537 $Description .= " on ".showArch(getArch(1));
17538 }
17539 }
17540 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 +030017541 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017542 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17543 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17544 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017545 $Report .= "</div>\n<br/><br/><br/>\n";
17546 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017547 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017548 return $Report;
17549 }
17550 }
17551}
17552
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017553sub getLegend()
17554{
17555 return "<br/>
17556<table class='summary'>
17557<tr>
17558 <td class='new'>added</td>
17559 <td class='passed'>compatible</td>
17560</tr>
17561<tr>
17562 <td class='warning'>warning</td>
17563 <td class='failed'>incompatible</td>
17564</tr></table>\n";
17565}
17566
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017567sub createReport()
17568{
17569 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017570 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017571 writeReport("Join", getReport("Join"));
17572 }
17573 elsif($DoubleReport)
17574 { # default
17575 writeReport("Binary", getReport("Binary"));
17576 writeReport("Source", getReport("Source"));
17577 }
17578 elsif($BinaryOnly)
17579 { # --binary
17580 writeReport("Binary", getReport("Binary"));
17581 }
17582 elsif($SourceOnly)
17583 { # --source
17584 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017585 }
17586}
17587
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017588sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017589{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017590 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017591
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017592 $Footer .= "<hr/>";
17593 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017594 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017595 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017596 $Footer .= "<br/>\n";
17597
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017598 return $Footer;
17599}
17600
17601sub get_Report_Problems($$)
17602{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017603 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017604
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017605 my $Report = get_Report_TypeProblems($Severity, $Level);
17606 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017607 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017608 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017609
17610 if($Severity eq "Low" or $Severity eq "Safe") {
17611 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017612 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017614 if($ReportFormat eq "html")
17615 {
17616 if($Report)
17617 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017618 if($JoinReport)
17619 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017620 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17622 }
17623 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017624 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017627 else
17628 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017629 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017630 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17631 }
17632 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017633 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017635 }
17636 }
17637 }
17638 return $Report;
17639}
17640
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017641sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017642{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017643 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17644 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17645 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17646 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017647 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17648 <meta name=\"keywords\" content=\"$Keywords\" />
17649 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017650 <title>
17651 $Title
17652 </title>
17653 <style type=\"text/css\">
17654 $Styles
17655 </style>
17656 <script type=\"text/javascript\" language=\"JavaScript\">
17657 <!--
17658 $Scripts
17659 -->
17660 </script>
17661 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017662}
17663
17664sub insertIDs($)
17665{
17666 my $Text = $_[0];
17667 while($Text=~/CONTENT_ID/)
17668 {
17669 if(int($Content_Counter)%2) {
17670 $ContentID -= 1;
17671 }
17672 $Text=~s/CONTENT_ID/c_$ContentID/;
17673 $ContentID += 1;
17674 $Content_Counter += 1;
17675 }
17676 return $Text;
17677}
17678
17679sub checkPreprocessedUnit($)
17680{
17681 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017682 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017683 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017684 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017685
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017686 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017687 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017688 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017689 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017690 chomp($Line);
17691 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017692 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017693 $CurHeader = path_format($1, $OSgroup);
17694 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017695 $CurClass = "";
17696
17697 if(index($CurHeader, $TMP_DIR)==0) {
17698 next;
17699 }
17700
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017701 if(substr($CurHeaderName, 0, 1) eq "<")
17702 { # <built-in>, <command-line>, etc.
17703 $CurHeaderName = "";
17704 $CurHeader = "";
17705 }
17706
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017707 if($ExtraInfo)
17708 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017709 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017710 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17711 }
17712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017713 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017714 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017715 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017716 if($CurHeaderName)
17717 {
17718 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17719 and not $Registered_Headers{$Version}{$CurHeader})
17720 { # not a target
17721 next;
17722 }
17723 if(not is_target_header($CurHeaderName, 1)
17724 and not is_target_header($CurHeaderName, 2))
17725 { # user-defined header
17726 next;
17727 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017728 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017729 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017730
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017731 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017732 {
17733 my ($Name, $Value) = ($1, $2);
17734 if(not $Constants{$Version}{$Name}{"Access"})
17735 {
17736 $Constants{$Version}{$Name}{"Access"} = "public";
17737 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017738 if($CurHeaderName) {
17739 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17740 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017741 }
17742 }
17743 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17744 $Constants{$Version}{$1}{"Access"} = "private";
17745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017746 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017747 else
17748 {
17749 if(defined $ExtraDump)
17750 {
17751 if($Line=~/(\w+)\s*\(/)
17752 { # functions
17753 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17754 }
17755 #elsif($Line=~/(\w+)\s*;/)
17756 #{ # data
17757 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17758 #}
17759 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17760 $CurClass = $2;
17761 }
17762 }
17763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017764 }
17765 close(PREPROC);
17766 foreach my $Constant (keys(%{$Constants{$Version}}))
17767 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017768 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17769 {
17770 delete($Constants{$Version}{$Constant});
17771 next;
17772 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017773 if(not $ExtraDump and ($Constant=~/_h\Z/i
17774 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017775 { # skip
17776 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017777 }
17778 else {
17779 delete($Constants{$Version}{$Constant}{"Access"});
17780 }
17781 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017782 if($Debug)
17783 {
17784 mkpath($DEBUG_PATH{$Version});
17785 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017787}
17788
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017789sub uncoverConstant($$)
17790{
17791 my ($LibVersion, $Constant) = @_;
17792 return "" if(not $LibVersion or not $Constant);
17793 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17794 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17795 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17796 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017797
17798 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017799 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017800 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17801 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017802 {
17803 push(@RecurConstant, $Constant);
17804 my $Uncovered = uncoverConstant($LibVersion, $Value);
17805 if($Uncovered ne "") {
17806 $Value = $Uncovered;
17807 }
17808 pop(@RecurConstant);
17809 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017810
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017811 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017812 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017813 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17814 }
17815 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17816}
17817
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017818sub simpleConstant($$)
17819{
17820 my ($LibVersion, $Value) = @_;
17821 if($Value=~/\W/)
17822 {
17823 my $Value_Copy = $Value;
17824 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17825 {
17826 my $Word = $1;
17827 if($Value!~/$Word\s*\(/)
17828 {
17829 my $Val = uncoverConstant($LibVersion, $Word);
17830 if($Val ne "")
17831 {
17832 $Value=~s/\b$Word\b/$Val/g;
17833 }
17834 }
17835 }
17836 }
17837 return $Value;
17838}
17839
17840sub computeValue($)
17841{
17842 my $Value = $_[0];
17843
17844 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17845 return $1;
17846 }
17847
17848 if($Value=~/\A[\d\-\+()]+\Z/) {
17849 return eval($Value);
17850 }
17851
17852 return $Value;
17853}
17854
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017855my %IgnoreConstant = map {$_=>1} (
17856 "VERSION",
17857 "VERSIONCODE",
17858 "VERNUM",
17859 "VERS_INFO",
17860 "PATCHLEVEL",
17861 "INSTALLPREFIX",
17862 "VBUILD",
17863 "VPATCH",
17864 "VMINOR",
17865 "BUILD_STRING",
17866 "BUILD_TIME",
17867 "PACKAGE_STRING",
17868 "PRODUCTION",
17869 "CONFIGURE_COMMAND",
17870 "INSTALLDIR",
17871 "BINDIR",
17872 "CONFIG_FILE_PATH",
17873 "DATADIR",
17874 "EXTENSION_DIR",
17875 "INCLUDE_PATH",
17876 "LIBDIR",
17877 "LOCALSTATEDIR",
17878 "SBINDIR",
17879 "SYSCONFDIR",
17880 "RELEASE",
17881 "SOURCE_ID",
17882 "SUBMINOR",
17883 "MINOR",
17884 "MINNOR",
17885 "MINORVERSION",
17886 "MAJOR",
17887 "MAJORVERSION",
17888 "MICRO",
17889 "MICROVERSION",
17890 "BINARY_AGE",
17891 "INTERFACE_AGE",
17892 "CORE_ABI",
17893 "PATCH",
17894 "COPYRIGHT",
17895 "TIMESTAMP",
17896 "REVISION",
17897 "PACKAGE_TAG",
17898 "PACKAGEDATE",
17899 "NUMVERSION",
17900 "Release",
17901 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017902);
17903
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017904sub constantFilter($$$)
17905{
17906 my ($Name, $Value, $Level) = @_;
17907
17908 if($Level eq "Binary")
17909 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017910 if($Name=~/_t\Z/)
17911 { # __malloc_ptr_t
17912 return 1;
17913 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017914 foreach (keys(%IgnoreConstant))
17915 {
17916 if($Name=~/(\A|_)$_(_|\Z)/)
17917 { # version
17918 return 1;
17919 }
17920 if(/\A[A-Z].*[a-z]\Z/)
17921 {
17922 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17923 { # version
17924 return 1;
17925 }
17926 }
17927 }
17928 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17929 { # version
17930 return 1;
17931 }
17932 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17933 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17934 return 1;
17935 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017936
17937 if($Value=~/\A["'].*['"]/i)
17938 { # string
17939 return 0;
17940 }
17941
17942 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17943 { # static int gcry_pth_init
17944 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017945 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017946 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017947 return 1;
17948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017949 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017950 { # foo(p)
17951 return 1;
17952 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017953 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017954 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017955 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017956 return 1;
17957 }
17958 }
17959
17960 return 0;
17961}
17962
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017963sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017964{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017965 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017966 foreach my $Constant (keys(%{$Constants{1}}))
17967 {
17968 if($SkipConstants{1}{$Constant})
17969 { # skipped by the user
17970 next;
17971 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017972
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017973 if(my $Header = $Constants{1}{$Constant}{"Header"})
17974 {
17975 if(not is_target_header($Header, 1)
17976 and not is_target_header($Header, 2))
17977 { # user-defined header
17978 next;
17979 }
17980 }
17981 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017982 next;
17983 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017984
17985 my $Old_Value = uncoverConstant(1, $Constant);
17986
17987 if(constantFilter($Constant, $Old_Value, $Level))
17988 { # separate binary and source problems
17989 next;
17990 }
17991
17992 if(not defined $Constants{2}{$Constant}{"Value"})
17993 { # removed
17994 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17995 "Target"=>$Constant,
17996 "Old_Value"=>$Old_Value );
17997 next;
17998 }
17999
18000 if($Constants{2}{$Constant}{"Value"} eq "")
18001 { # empty value
18002 # TODO: implement a rule
18003 next;
18004 }
18005
18006 my $New_Value = uncoverConstant(2, $Constant);
18007
18008 my $Old_Value_Pure = $Old_Value;
18009 my $New_Value_Pure = $New_Value;
18010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018011 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18012 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18013 $New_Value_Pure=~s/(\W)\s+/$1/g;
18014 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018015
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018016 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018017
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018018 if($New_Value_Pure ne $Old_Value_Pure)
18019 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018020 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18021 { # complex values
18022 next;
18023 }
18024 if(computeValue($Old_Value) eq computeValue($New_Value))
18025 { # expressions
18026 next;
18027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018028 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18029 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18030 next;
18031 }
18032 if($Old_Value eq "0" and $New_Value eq "NULL")
18033 { # 0 => NULL
18034 next;
18035 }
18036 if($Old_Value eq "NULL" and $New_Value eq "0")
18037 { # NULL => 0
18038 next;
18039 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018040 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018041 "Target"=>$Constant,
18042 "Old_Value"=>$Old_Value,
18043 "New_Value"=>$New_Value );
18044 }
18045 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018046
18047 foreach my $Constant (keys(%{$Constants{2}}))
18048 {
18049 if(not defined $Constants{1}{$Constant}{"Value"})
18050 {
18051 if($SkipConstants{2}{$Constant})
18052 { # skipped by the user
18053 next;
18054 }
18055
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018056 if(my $Header = $Constants{2}{$Constant}{"Header"})
18057 {
18058 if(not is_target_header($Header, 1)
18059 and not is_target_header($Header, 2))
18060 { # user-defined header
18061 next;
18062 }
18063 }
18064 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018065 next;
18066 }
18067
18068 my $New_Value = uncoverConstant(2, $Constant);
18069 if(not defined $New_Value or $New_Value eq "") {
18070 next;
18071 }
18072
18073 if(constantFilter($Constant, $New_Value, $Level))
18074 { # separate binary and source problems
18075 next;
18076 }
18077
18078 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18079 "Target"=>$Constant,
18080 "New_Value"=>$New_Value );
18081 }
18082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018083}
18084
18085sub convert_integer($)
18086{
18087 my $Value = $_[0];
18088 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018089 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018090 return hex($Value);
18091 }
18092 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018093 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018094 return oct($Value);
18095 }
18096 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018097 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018098 return oct($Value);
18099 }
18100 else {
18101 return $Value;
18102 }
18103}
18104
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018105sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018106{
18107 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018108 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018109 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018110 {
18111 if($LibVersion==1)
18112 {
18113 printMsg("WARNING", "checking headers only");
18114 $CheckHeadersOnly = 1;
18115 }
18116 else {
18117 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18118 }
18119 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018120
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018121 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018122 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018123 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018124
18125 if($CheckUndefined)
18126 {
18127 my %UndefinedLibs = ();
18128
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018129 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18130
18131 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018132 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018133 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018134 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018135 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018136 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018137 if($Symbol_Library{$LibVersion}{$Symbol}
18138 or $DepSymbol_Library{$LibVersion}{$Symbol})
18139 { # exported by target library
18140 next;
18141 }
18142 if(index($Symbol, '@')!=-1)
18143 { # exported default symbol version (@@)
18144 $Symbol=~s/\@/\@\@/;
18145 if($Symbol_Library{$LibVersion}{$Symbol}
18146 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18147 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018148 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018149 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018150 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18151 $UndefinedLibs{$Path} = 1;
18152 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018153 }
18154 }
18155 }
18156 if($ExtraInfo)
18157 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018158 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018159 {
18160 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018161 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018162 foreach (@Paths)
18163 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018164 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018165 my ($Dir, $Name) = separate_path($_);
18166
18167 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018168 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018169 }
18170
18171 $Name = parse_libname($Name, "name", $OStarget);
18172 $Name=~s/\Alib//;
18173
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018174 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018175 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018176
18177 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18178 {
18179 $LibString = " -L".esc($Dir).$LibString;
18180 }
18181
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018182 writeFile($ExtraInfo."/libs-string", $LibString);
18183 }
18184 }
18185 }
18186
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018187 if($ExtraInfo) {
18188 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18189 }
18190
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018191 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018192 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018193 if($#LibPaths!=-1)
18194 {
18195 if(not keys(%{$Symbol_Library{$LibVersion}}))
18196 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018197 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018198 printMsg("WARNING", "checking headers only");
18199 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018200 }
18201 }
18202 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018203
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018204 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018205 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018206}
18207
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018208my %Prefix_Lib_Map=(
18209 # symbols for autodetecting library dependencies (by prefix)
18210 "pthread_" => ["libpthread"],
18211 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18212 "cairo_" => ["libcairo"],
18213 "gtk_" => ["libgtk-x11-2.0"],
18214 "atk_" => ["libatk-1.0"],
18215 "gdk_" => ["libgdk-x11-2.0"],
18216 "gl" => ["libGL"],
18217 "glu" => ["libGLU"],
18218 "popt" => ["libpopt"],
18219 "Py" => ["libpython"],
18220 "jpeg_" => ["libjpeg"],
18221 "BZ2_" => ["libbz2"],
18222 "Fc" => ["libfontconfig"],
18223 "Xft" => ["libXft"],
18224 "SSL_" => ["libssl"],
18225 "sem_" => ["libpthread"],
18226 "snd_" => ["libasound"],
18227 "art_" => ["libart_lgpl_2"],
18228 "dbus_g" => ["libdbus-glib-1"],
18229 "GOMP_" => ["libgomp"],
18230 "omp_" => ["libgomp"],
18231 "cms" => ["liblcms"]
18232);
18233
18234my %Pattern_Lib_Map=(
18235 "SL[a-z]" => ["libslang"]
18236);
18237
18238my %Symbol_Lib_Map=(
18239 # symbols for autodetecting library dependencies (by name)
18240 "pow" => "libm",
18241 "fmod" => "libm",
18242 "sin" => "libm",
18243 "floor" => "libm",
18244 "cos" => "libm",
18245 "dlopen" => "libdl",
18246 "deflate" => "libz",
18247 "inflate" => "libz",
18248 "move_panel" => "libpanel",
18249 "XOpenDisplay" => "libX11",
18250 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018251 "clock_gettime" => "librt",
18252 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018253);
18254
18255sub find_SymbolLibs($$)
18256{
18257 my ($LibVersion, $Symbol) = @_;
18258
18259 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18260 { # debug symbols
18261 return ();
18262 }
18263
18264 my %Paths = ();
18265
18266 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18267 {
18268 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18269 $Paths{$Path} = 1;
18270 }
18271 }
18272
18273 if(my $SymbolPrefix = getPrefix($Symbol))
18274 {
18275 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18276 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18277 }
18278
18279 if(not keys(%Paths))
18280 {
18281 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18282 {
18283 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18284 {
18285 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18286 $Paths{$Path} = 1;
18287 }
18288 }
18289 }
18290 }
18291
18292 if(not keys(%Paths))
18293 {
18294 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18295 {
18296 if($Symbol=~/\A$Prefix/)
18297 {
18298 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18299 {
18300 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18301 $Paths{$Path} = 1;
18302 }
18303 }
18304 }
18305 }
18306 }
18307
18308 if(not keys(%Paths))
18309 {
18310 if($SymbolPrefix)
18311 { # try to find a library by symbol prefix
18312 if($SymbolPrefix eq "inotify" and
18313 index($Symbol, "\@GLIBC")!=-1)
18314 {
18315 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18316 $Paths{$Path} = 1;
18317 }
18318 }
18319 else
18320 {
18321 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18322 $Paths{$Path} = 1;
18323 }
18324 }
18325 }
18326 }
18327
18328 if(my @Paths = keys(%Paths)) {
18329 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18330 }
18331 }
18332 return keys(%Paths);
18333}
18334
18335sub get_LibPath_Prefix($$)
18336{
18337 my ($LibVersion, $Prefix) = @_;
18338
18339 $Prefix = lc($Prefix);
18340 $Prefix=~s/[_]+\Z//g;
18341
18342 foreach ("-2", "2", "-1", "1", "")
18343 { # libgnome-2.so
18344 # libxml2.so
18345 # libdbus-1.so
18346 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18347 return $Path;
18348 }
18349 }
18350 return "";
18351}
18352
18353sub getPrefix($)
18354{
18355 my $Str = $_[0];
18356 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18357 { # XmuValidArea: Xmu
18358 return $1;
18359 }
18360 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18361 { # snfReadFont: snf
18362 return $1;
18363 }
18364 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18365 { # XRRTimes: XRR
18366 return $1;
18367 }
18368 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18369 { # H5HF_delete: H5
18370 return $1;
18371 }
18372 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18373 { # alarm_event_add: alarm_
18374 return $1;
18375 }
18376 elsif($Str=~/\A(([a-z])\2{1,})/i)
18377 { # ffopen
18378 return $1;
18379 }
18380 return "";
18381}
18382
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018383sub getSymbolSize($$)
18384{ # size from the shared library
18385 my ($Symbol, $LibVersion) = @_;
18386 return 0 if(not $Symbol);
18387 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18388 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18389 {
18390 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18391 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18392 {
18393 if($Size<0) {
18394 return -$Size;
18395 }
18396 }
18397 }
18398 return 0;
18399}
18400
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018401sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018402{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18403 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018404 my ($Name, $Type) = @_;
18405
18406 # single
18407 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018408 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018409 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018410 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018411 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018412
18413 # double
18414 if($Name=~/$DEFAULT_STD_PARMS/)
18415 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018416 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018417 {
18418 my ($ShortName, $FuncParams) = split_Signature($Name);
18419
18420 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18421 {
18422 if(index($FParam, "<")!=-1)
18423 {
18424 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18425 my $FParam_N = canonifyName($FParam, "T");
18426 if($FParam_N ne $FParam) {
18427 $Name=~s/\Q$FParam\E/$FParam_N/g;
18428 }
18429 }
18430 }
18431 }
18432 elsif($Type eq "T")
18433 {
18434 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18435
18436 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018437 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018438 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018439 my $FParam = $TParams[0];
18440 foreach my $Pos (1 .. $#TParams)
18441 {
18442 my $TParam = $TParams[$Pos];
18443 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18444 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18445 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018446 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018447 }
18448 }
18449 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018450 if($Type eq "S") {
18451 return formatName($Name, "S");
18452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018453 return $Name;
18454}
18455
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018456sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018457{
18458 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018459 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018460 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018461 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018462 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018463 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018464 next if($tr_name{$Symbol});
18465 $Symbol=~s/[\@\$]+(.*)\Z//;
18466 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018467 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018468 elsif(index($Symbol, "?")==0)
18469 {
18470 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018471 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018472 }
18473 else
18474 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018475 $tr_name{$Symbol} = $Symbol;
18476 $mangled_name_gcc{$Symbol} = $Symbol;
18477 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018478 }
18479 }
18480 if($#MnglNames1 > -1)
18481 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018482 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018483 foreach my $MnglName (@MnglNames1)
18484 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018485 if(my $Unmangled = pop(@UnmangledNames))
18486 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018487 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018488 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18489 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18490 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018491 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018492 and $tr_name{$MnglName}=~/vtable for (.+)/)
18493 { # bind class name and v-table symbol
18494 my $ClassName = $1;
18495 $ClassVTable{$ClassName} = $MnglName;
18496 $VTableClass{$MnglName} = $ClassName;
18497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018498 }
18499 }
18500 }
18501 if($#MnglNames2 > -1)
18502 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018503 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018504 foreach my $MnglName (@MnglNames2)
18505 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018506 if(my $Unmangled = pop(@UnmangledNames))
18507 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018508 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018509 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018511 }
18512 }
18513 return \%tr_name;
18514}
18515
18516sub link_symbol($$$)
18517{
18518 my ($Symbol, $RunWith, $Deps) = @_;
18519 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18520 return 1;
18521 }
18522 if($Deps eq "+Deps")
18523 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018524 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018525 return 1;
18526 }
18527 }
18528 return 0;
18529}
18530
18531sub link_symbol_internal($$$)
18532{
18533 my ($Symbol, $RunWith, $Where) = @_;
18534 return 0 if(not $Where or not $Symbol);
18535 if($Where->{$RunWith}{$Symbol})
18536 { # the exact match by symbol name
18537 return 1;
18538 }
18539 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18540 { # indirect symbol version, i.e.
18541 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018542 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018543 if($Where->{$RunWith}{$VSym}) {
18544 return 1;
18545 }
18546 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018547 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018548 if($Sym and $Ver)
18549 { # search for the symbol with the same version
18550 # or without version
18551 if($Where->{$RunWith}{$Sym})
18552 { # old: foo@v|foo@@v
18553 # new: foo
18554 return 1;
18555 }
18556 if($Where->{$RunWith}{$Sym."\@".$Ver})
18557 { # old: foo|foo@@v
18558 # new: foo@v
18559 return 1;
18560 }
18561 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18562 { # old: foo|foo@v
18563 # new: foo@@v
18564 return 1;
18565 }
18566 }
18567 return 0;
18568}
18569
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018570sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018571{
18572 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018573 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018574 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018575 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018576 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018577 my $NM = get_CmdPath("nm");
18578 if(not $NM) {
18579 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018580 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018581 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018582 while(<APP>)
18583 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018584 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018585 push(@Imported, $1);
18586 }
18587 }
18588 close(APP);
18589 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018590 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018591 {
18592 my $DumpBinCmd = get_CmdPath("dumpbin");
18593 if(not $DumpBinCmd) {
18594 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18595 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018596 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018597 while(<APP>)
18598 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018599 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18600 push(@Imported, $1);
18601 }
18602 }
18603 close(APP);
18604 }
18605 else
18606 {
18607 my $ReadelfCmd = get_CmdPath("readelf");
18608 if(not $ReadelfCmd) {
18609 exitStatus("Not_Found", "can't find \"readelf\"");
18610 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018611 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018612 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018613 while(<APP>)
18614 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018615 if(defined $symtab)
18616 { # do nothing with symtab
18617 if(index($_, "'.dynsym'")!=-1)
18618 { # dynamic table
18619 $symtab = undef;
18620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018621 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018622 elsif(index($_, "'.symtab'")!=-1)
18623 { # symbol table
18624 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018625 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018626 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018627 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018628 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18629 if($Ndx eq "UND")
18630 { # only imported symbols
18631 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018632 }
18633 }
18634 }
18635 close(APP);
18636 }
18637 return @Imported;
18638}
18639
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018640my %ELF_BIND = map {$_=>1} (
18641 "WEAK",
18642 "GLOBAL"
18643);
18644
18645my %ELF_TYPE = map {$_=>1} (
18646 "FUNC",
18647 "IFUNC",
18648 "OBJECT",
18649 "COMMON"
18650);
18651
18652my %ELF_VIS = map {$_=>1} (
18653 "DEFAULT",
18654 "PROTECTED"
18655);
18656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018657sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018658{ # read the line of 'readelf' output corresponding to the symbol
18659 my @Info = split(/\s+/, $_[0]);
18660 # Num: Value Size Type Bind Vis Ndx Name
18661 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018662 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018663 shift(@Info); # spaces
18664 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018665
18666 if($#Info==7)
18667 { # UND SYMBOL (N)
18668 if($Info[7]=~/\(\d+\)/) {
18669 pop(@Info);
18670 }
18671 }
18672
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018673 if($#Info!=6)
18674 { # other lines
18675 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018676 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018677 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018678 return () if(not defined $ELF_BIND{$Info[3]});
18679 return () if(not defined $ELF_VIS{$Info[4]});
18680 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18681 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18682 return ();
18683 }
18684 if($OStarget eq "symbian")
18685 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18686 if(index($Info[6], "_._.absent_export_")!=-1)
18687 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18688 return ();
18689 }
18690 $Info[6]=~s/\@.+//g; # remove version
18691 }
18692 if(index($Info[2], "0x") == 0)
18693 { # size == 0x3d158
18694 $Info[2] = hex($Info[2]);
18695 }
18696 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018697}
18698
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018699sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018700{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018701 my ($LibVersion, $Name) = @_;
18702 return "" if(not $LibVersion or not $Name);
18703 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18704 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018705 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018706 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18707}
18708
18709sub get_LibPath_I($$)
18710{
18711 my ($LibVersion, $Name) = @_;
18712 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018713 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018714 if(-f $Name)
18715 { # absolute path
18716 return $Name;
18717 }
18718 else
18719 { # broken
18720 return "";
18721 }
18722 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018723 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018724 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018725 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018726 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018727 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018728 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018729 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018730 }
18731 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18732 { # ldconfig default paths
18733 return $DefaultPath;
18734 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018735 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018736 { # search in default linker directories
18737 # and then in all system paths
18738 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018739 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018740 }
18741 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018742 if(not defined $Cache{"checkSystemFiles"}) {
18743 checkSystemFiles();
18744 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018745 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18746 return $AllObjects[0];
18747 }
18748 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18749 {
18750 if($ShortName ne $Name)
18751 { # FIXME: check this case
18752 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18753 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018754 }
18755 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018756 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018757 # can't find
18758 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018759}
18760
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018762{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018763 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18764 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018765
18766 my $Real_Path = realpath($Lib_Path);
18767
18768 if(not $Real_Path)
18769 { # broken link
18770 return ();
18771 }
18772
18773 my $Lib_Name = get_filename($Real_Path);
18774
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018775 if($ExtraInfo)
18776 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018777 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018778 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018779 }
18780
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018781 if($IsNeededLib)
18782 {
18783 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18784 return ();
18785 }
18786 }
18787 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018788 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018789
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018790 push(@RecurLib, $Lib_Name);
18791 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018792 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18793
18794 if(not $IsNeededLib)
18795 { # special cases: libstdc++ and libc
18796 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18797 {
18798 if($ShortName eq "libstdc++")
18799 { # libstdc++.so.6
18800 $STDCXX_TESTING = 1;
18801 }
18802 elsif($ShortName eq "libc")
18803 { # libc-2.11.3.so
18804 $GLIBC_TESTING = 1;
18805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018806 }
18807 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018808 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018809 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018810 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018811 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018812 mkpath(get_dirname($DebugPath));
18813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018814 if($OStarget eq "macos")
18815 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018816 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018817 if(not $NM) {
18818 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018819 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018820 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018821 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018822 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018823 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018824 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018825 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018826 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018827 else
18828 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018829 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018831 while(<LIB>)
18832 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018833 if($CheckUndefined)
18834 {
18835 if(not $IsNeededLib)
18836 {
18837 if(/ U _([\w\$]+)\s*\Z/)
18838 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018839 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018840 next;
18841 }
18842 }
18843 }
18844
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018845 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018846 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018847 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018848 if($IsNeededLib)
18849 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018850 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018851 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018852 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18853 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018856 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018857 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018858 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18859 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018860 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18861 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018862 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018863 setLanguage($LibVersion, "C++");
18864 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 }
18867 }
18868 }
18869 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018870
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018871 if($Deps)
18872 {
18873 if($LIB_TYPE eq "dynamic")
18874 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018875
18876 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018877 if(not $OtoolCmd) {
18878 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018879 }
18880
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018881 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18882 while(<LIB>)
18883 {
18884 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18885 and $1 ne $Lib_Path) {
18886 $NeededLib{$1} = 1;
18887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018889 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 }
18892 }
18893 elsif($OStarget eq "windows")
18894 { # Windows *.dll, *.lib
18895 my $DumpBinCmd = get_CmdPath("dumpbin");
18896 if(not $DumpBinCmd) {
18897 exitStatus("Not_Found", "can't find \"dumpbin\"");
18898 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018899 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018900 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018901 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018902 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018903 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018904 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018905 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018906 else
18907 { # write to pipe
18908 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018910 while(<LIB>)
18911 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18912 # 1198 4AD SetThreadToken (forwarded to ...)
18913 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018914 # 1 0 00005B30 ??0?N = ... (with pdb)
18915 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018917 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018918 { # dynamic, static and forwarded symbols
18919 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018920 if($IsNeededLib)
18921 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018922 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018923 {
18924 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18925 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18926 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018927 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018928 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018929 {
18930 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18931 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018932 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18933 {
18934 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18935 setLanguage($LibVersion, "C++");
18936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018938 }
18939 }
18940 }
18941 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018942
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943 if($Deps)
18944 {
18945 if($LIB_TYPE eq "dynamic")
18946 { # dependencies
18947 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18948 while(<LIB>)
18949 {
18950 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18951 and $1 ne $Lib_Path) {
18952 $NeededLib{path_format($1, $OSgroup)} = 1;
18953 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018954 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018955 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018957 }
18958 }
18959 else
18960 { # Unix; *.so, *.a
18961 # Symbian: *.dso, *.lib
18962 my $ReadelfCmd = get_CmdPath("readelf");
18963 if(not $ReadelfCmd) {
18964 exitStatus("Not_Found", "can't find \"readelf\"");
18965 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018966 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018967 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018968 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018969 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018970 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018971 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018972 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018973 else
18974 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018975 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018976 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018977 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018978 while(<LIB>)
18979 {
18980 if($LIB_TYPE eq "dynamic")
18981 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018982 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018983 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018985 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018986 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018987 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018988 # do nothing with symtab
18989 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018991 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018992 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018993 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018994 next;
18995 }
18996 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018997 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018998 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018999 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019000 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019001 if($CheckUndefined)
19002 {
19003 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019004 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019005 }
19006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 next;
19008 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019009 if($Bind eq "WEAK")
19010 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019011 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019012 if($Weak eq "-Weak")
19013 { # skip WEAK symbols
19014 next;
19015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019016 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019017 my $Short = $Symbol;
19018 $Short=~s/\@.+//g;
19019 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019021 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19022 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019023 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019024 if($IsNeededLib)
19025 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019026 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019027 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019028 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19029 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019032 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019033 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019034 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19035 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19036 if($Vers)
19037 {
19038 if($LIB_EXT eq "so")
19039 { # value
19040 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19041 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019043 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019044 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19045 {
19046 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19047 setLanguage($LibVersion, "C++");
19048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019050 }
19051 }
19052 }
19053 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019054
19055 if($Deps and $LIB_TYPE eq "dynamic")
19056 { # dynamic library specifics
19057 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19058 open(LIB, $Cmd." |");
19059
19060 while(<LIB>)
19061 {
19062 if(/NEEDED.+\[([^\[\]]+)\]/)
19063 { # dependencies:
19064 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19065 $NeededLib{$1} = 1;
19066 }
19067 }
19068
19069 close(LIB);
19070 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019071 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019072 if($Vers)
19073 {
19074 if(not $IsNeededLib and $LIB_EXT eq "so")
19075 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019076 my %Found = ();
19077
19078 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019079 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019080 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 next if(index($Symbol,"\@")==-1);
19082 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019083 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019084 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019085 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019086 if($Symbol_SameValue ne $Symbol
19087 and index($Symbol_SameValue,"\@")==-1)
19088 {
19089 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019090 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019091 last;
19092 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019093 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019094 }
19095 }
19096
19097 # default
19098 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19099 {
19100 next if(defined $Found{$Symbol});
19101 next if(index($Symbol,"\@\@")==-1);
19102
19103 if($Symbol=~/\A([^\@]*)\@\@/
19104 and not $SymVer{$LibVersion}{$1})
19105 {
19106 $SymVer{$LibVersion}{$1} = $Symbol;
19107 $Found{$Symbol} = 1;
19108 }
19109 }
19110
19111 # non-default
19112 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19113 {
19114 next if(defined $Found{$Symbol});
19115 next if(index($Symbol,"\@")==-1);
19116
19117 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19118 and not $SymVer{$LibVersion}{$1})
19119 {
19120 $SymVer{$LibVersion}{$1} = $Symbol;
19121 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019122 }
19123 }
19124 }
19125 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019126 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019127 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019128 foreach my $DyLib (sort keys(%NeededLib))
19129 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019130 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19131
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019132 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19133 {
19134 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19135 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19136 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019138 }
19139 }
19140 pop(@RecurLib);
19141 return $Library_Symbol{$LibVersion};
19142}
19143
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019144sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019145{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019147 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019148 return keys(%Prefixes);
19149}
19150
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019151sub get_prefixes_I($$)
19152{
19153 foreach my $P (@{$_[0]})
19154 {
19155 my @Parts = reverse(split(/[\/\\]+/, $P));
19156 my $Name = $Parts[0];
19157 foreach (1 .. $#Parts)
19158 {
19159 $_[1]->{$Name}{$P} = 1;
19160 last if($_>4 or $Parts[$_] eq "include");
19161 $Name = $Parts[$_].$SLASH.$Name;
19162 }
19163 }
19164}
19165
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019166sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019167{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019168 $Cache{"checkSystemFiles"} = 1;
19169
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019170 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019171
19172 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 {
19174 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019175
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019176 my @Files = cmd_find($DevelPath,"f");
19177 foreach my $Link (cmd_find($DevelPath,"l"))
19178 { # add symbolic links
19179 if(-f $Link) {
19180 push(@Files, $Link);
19181 }
19182 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019183
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019184 # search for headers in /usr/lib
19185 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19186 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19187 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019188
19189 # search for libraries in /usr/lib (including symbolic links)
19190 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19191 foreach my $Path (@Libs)
19192 {
19193 my $N = get_filename($Path);
19194 $SystemObjects{$N}{$Path} = 1;
19195 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019196 }
19197 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019198
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019199 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019200 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019201 next if(not -d $DevelPath);
19202 # search for all header files in the /usr/include
19203 # with or without extension (ncurses.h, QtCore, ...)
19204 push(@SysHeaders, cmd_find($DevelPath,"f"));
19205 foreach my $Link (cmd_find($DevelPath,"l"))
19206 { # add symbolic links
19207 if(-f $Link) {
19208 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019210 }
19211 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019212 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019213}
19214
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019215sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019216{
19217 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019218 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019219 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19220 {
19221 if(not -e $Dest) {
19222 exitStatus("Access_Error", "can't access \'$Dest\'");
19223 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019224 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019225 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19226 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019227 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019228 }
19229 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019230 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019231}
19232
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019233sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234{
19235 my ($Path, $LibVersion) = @_;
19236 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019237 my $Name = get_filename($Path);
19238 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019239 return 1;
19240 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019241 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19243 return 1;
19244 }
19245 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19246 {
19247 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19248 return 1;
19249 }
19250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019251 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019253 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 return 1;
19255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019256 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019257 return 1;
19258 }
19259 }
19260 return 0;
19261}
19262
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019263sub specificHeader($$)
19264{
19265 my ($Header, $Spec) = @_;
19266 my $Name = get_filename($Header);
19267
19268 if($Spec eq "windows")
19269 {# MS Windows
19270 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19271 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19272 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19273 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19274 my @Dirs = (
19275 "win32",
19276 "win64",
19277 "win",
19278 "windows",
19279 "msvcrt"
19280 ); # /gsf-win32/
19281 if(my $DIRs = join("|", @Dirs)) {
19282 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19283 }
19284 }
19285 elsif($Spec eq "macos")
19286 { # Mac OS
19287 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19288 }
19289
19290 return 0;
19291}
19292
19293sub skipAlienHeader($)
19294{
19295 my $Path = $_[0];
19296 my $Name = get_filename($Path);
19297 my $Dir = get_dirname($Path);
19298
19299 if($Tolerance=~/2/)
19300 { # 2 - skip internal headers
19301 my @Terms = (
19302 "p",
19303 "priv",
19304 "int",
19305 "impl",
19306 "implementation",
19307 "internal",
19308 "private",
19309 "old",
19310 "compat",
19311 "debug",
19312 "test",
19313 "gen"
19314 );
19315
19316 my @Dirs = (
19317 "private",
19318 "priv",
19319 "port",
19320 "impl",
19321 "internal",
19322 "detail",
19323 "details",
19324 "old",
19325 "compat",
19326 "debug",
19327 "config",
19328 "compiler",
19329 "platform",
19330 "test"
19331 );
19332
19333 if(my $TERMs = join("|", @Terms)) {
19334 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19335 }
19336 if(my $DIRs = join("|", @Dirs)) {
19337 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19338 }
19339
19340 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19341 }
19342
19343 if($Tolerance=~/1/)
19344 { # 1 - skip non-Linux headers
19345 if($OSgroup ne "windows")
19346 {
19347 if(specificHeader($Path, "windows")) {
19348 return 1;
19349 }
19350 }
19351 if($OSgroup ne "macos")
19352 {
19353 if(specificHeader($Path, "macos")) {
19354 return 1;
19355 }
19356 }
19357 }
19358
19359 # valid
19360 return 0;
19361}
19362
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019363sub skipHeader($$)
19364{
19365 my ($Path, $LibVersion) = @_;
19366 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019367 if(defined $Cache{"skipHeader"}{$Path}) {
19368 return $Cache{"skipHeader"}{$Path};
19369 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019370 if(defined $Tolerance and $Tolerance=~/1|2/)
19371 { # --tolerant
19372 if(skipAlienHeader($Path)) {
19373 return ($Cache{"skipHeader"}{$Path} = 1);
19374 }
19375 }
19376 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19377 return 0;
19378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019379 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19380}
19381
19382sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019383{ # returns:
19384 # 1 - if header should NOT be included and checked
19385 # 2 - if header should NOT be included, but should be checked
19386 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019387 my $Name = get_filename($Path);
19388 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019389 return $Kind;
19390 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019391 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19392 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019393 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019394 if(index($Path, $D)!=-1)
19395 {
19396 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19397 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 }
19400 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019401 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19402 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019403 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019404 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19405 {
19406 if($Name=~/$P/) {
19407 return $Kind;
19408 }
19409 if($P=~/[\/\\]/ and $Path=~/$P/) {
19410 return $Kind;
19411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019412 }
19413 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019414
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019415 return 0;
19416}
19417
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019418sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019419{
19420 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019421 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019422 { # system directory
19423 return;
19424 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019425 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019426 { # already registered
19427 return;
19428 }
19429 foreach my $Path (find_libs($Dir,"",1))
19430 {
19431 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019432 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019434 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019435 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19436}
19437
19438sub registerObject($$)
19439{
19440 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019441
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019442 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019443 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019444 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019445 {
19446 if(my $SONAME = getSONAME($Path)) {
19447 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19448 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019449 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019450 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19451 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019452 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019453
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019454 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019455 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019456 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019457 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019458 if($ObjArch ne getArch_GCC($LibVersion))
19459 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19460 $CheckedArch{$LibVersion} = 1;
19461 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 +040019462 }
19463 }
19464 }
19465}
19466
19467sub getArch_Object($)
19468{
19469 my $Path = $_[0];
19470
19471 my %MachineType = (
19472 "14C" => "x86",
19473 "8664" => "x86_64",
19474 "1C0" => "arm",
19475 "200" => "ia64"
19476 );
19477
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019478 my %ArchName = (
19479 "s390:31-bit" => "s390",
19480 "s390:64-bit" => "s390x",
19481 "powerpc:common" => "ppc32",
19482 "powerpc:common64" => "ppc64",
19483 "i386:x86-64" => "x86_64",
19484 "mips:3000" => "mips",
19485 "sparc:v8plus" => "sparcv9"
19486 );
19487
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019488 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019489 {
19490 my $DumpbinCmd = get_CmdPath("dumpbin");
19491 if(not $DumpbinCmd) {
19492 exitStatus("Not_Found", "can't find \"dumpbin\"");
19493 }
19494
19495 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19496 my $Out = `$Cmd`;
19497
19498 if($Out=~/(\w+)\smachine/)
19499 {
19500 if(my $Type = $MachineType{uc($1)})
19501 {
19502 return $Type;
19503 }
19504 }
19505 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019506 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019507 {
19508 my $ObjdumpCmd = get_CmdPath("objdump");
19509 if(not $ObjdumpCmd) {
19510 exitStatus("Not_Found", "can't find \"objdump\"");
19511 }
19512
19513 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019514
19515 if($OSgroup eq "windows") {
19516 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19517 }
19518 else {
19519 $Cmd = "LANG=$LOCALE ".$Cmd;
19520 }
19521 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019522
19523 if($Out=~/architecture:\s+([\w\-\:]+)/)
19524 {
19525 my $Arch = $1;
19526 if($Arch=~s/\:(.+)//)
19527 {
19528 my $Suffix = $1;
19529
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019530 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019531 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019532 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019533 }
19534 }
19535
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019536 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019537 $Arch = "x86";
19538 }
19539
19540 if($Arch eq "x86-64") {
19541 $Arch = "x86_64";
19542 }
19543
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019544 if($Arch eq "ia64-elf64") {
19545 $Arch = "ia64";
19546 }
19547
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019548 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019549 }
19550 }
19551 else
19552 { # macos, etc.
19553 # TODO
19554 }
19555
19556 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019557}
19558
19559sub getSONAME($)
19560{
19561 my $Path = $_[0];
19562 return if(not $Path);
19563 if(defined $Cache{"getSONAME"}{$Path}) {
19564 return $Cache{"getSONAME"}{$Path};
19565 }
19566 my $ObjdumpCmd = get_CmdPath("objdump");
19567 if(not $ObjdumpCmd) {
19568 exitStatus("Not_Found", "can't find \"objdump\"");
19569 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019570 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019571 if($OSgroup eq "windows") {
19572 $SonameCmd .= " | find \"SONAME\"";
19573 }
19574 else {
19575 $SonameCmd .= " | grep SONAME";
19576 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019577 if(my $SonameInfo = `$SonameCmd`)
19578 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019579 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19580 return ($Cache{"getSONAME"}{$Path} = $1);
19581 }
19582 }
19583 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019584}
19585
19586sub getSOPaths_Dest($$)
19587{
19588 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019589 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019590 return ();
19591 }
19592 if(-f $Dest)
19593 {
19594 if(not parse_libname($Dest, "name", $OStarget)) {
19595 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19596 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019597 registerObject($Dest, $LibVersion);
19598 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019599 return ($Dest);
19600 }
19601 elsif(-d $Dest)
19602 {
19603 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019604 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019605 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19607 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019608 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019609 { # all files and symlinks that match the name of a library
19610 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19611 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019612 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019613 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019614 }
19615 }
19616 }
19617 else
19618 { # search for all files and symlinks
19619 foreach my $Path (find_libs($Dest,"",""))
19620 {
19621 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019622 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019623 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019624 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625 }
19626 if($OSgroup eq "macos")
19627 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019628 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019629 {
19630 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019631 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019632 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019633 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19634 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019635 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019636 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637 }
19638 }
19639 }
19640 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019641 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019642 }
19643 else {
19644 return ();
19645 }
19646}
19647
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019648sub isCyclical($$)
19649{
19650 my ($Stack, $Value) = @_;
19651 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019652}
19653
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019654sub getGCC_Opts($)
19655{ # to use in module
19656 my $LibVersion = $_[0];
19657
19658 my @Opts = ();
19659
19660 if($CompilerOptions{$LibVersion})
19661 { # user-defined options
19662 push(@Opts, $CompilerOptions{$LibVersion});
19663 }
19664 if($GccOptions)
19665 { # additional
19666 push(@Opts, $GccOptions);
19667 }
19668
19669 if(@Opts) {
19670 return join(" ", @Opts);
19671 }
19672
19673 return undef;
19674}
19675
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019676sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019677{
19678 my $LibVersion = $_[0];
19679
19680 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19681 return $Cache{"getArch_GCC"}{$LibVersion};
19682 }
19683
19684 my $Arch = undef;
19685
19686 if($GCC_PATH)
19687 {
19688 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19689
19690 my $Cmd = $GCC_PATH." test.c -o test";
19691 if(my $Opts = getGCC_Opts($LibVersion))
19692 { # user-defined options
19693 $Cmd .= " ".$Opts;
19694 }
19695
19696 chdir($TMP_DIR);
19697 system($Cmd);
19698 chdir($ORIG_DIR);
19699
19700 $Arch = getArch_Object("$TMP_DIR/test");
19701
19702 unlink("$TMP_DIR/test.c");
19703 unlink("$TMP_DIR/test");
19704 }
19705
19706 if(not $Arch) {
19707 exitStatus("Error", "can't check ARCH type");
19708 }
19709
19710 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19711}
19712
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019713sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019714{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019715 my $LibVersion = $_[0];
19716
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019717 my $Size = undef;
19718
19719 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019720 if(my $Arch = getArch($LibVersion))
19721 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019722 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019723 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019724 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019725 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19726 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019727 }
19728 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019729
19730 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019731 {
19732 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019733
19734 my $Cmd = $GCC_PATH." -E -dD empty.h";
19735 if(my $Opts = getGCC_Opts($LibVersion))
19736 { # user-defined options
19737 $Cmd .= " ".$Opts;
19738 }
19739
19740 chdir($TMP_DIR);
19741 my $Defines = `$Cmd`;
19742 chdir($ORIG_DIR);
19743
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019744 unlink("$TMP_DIR/empty.h");
19745
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019746 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19747 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019748 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019749 }
19750 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19751 { # GCC 3
19752 my $PTRDIFF = $1;
19753 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019754 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019755 }
19756 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019757 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019758 }
19759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019760 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019761
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019762 if(not $Size) {
19763 exitStatus("Error", "can't check WORD size");
19764 }
19765
19766 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019767}
19768
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019769sub getWordSize($)
19770{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019771 return $WORD_SIZE{$_[0]};
19772}
19773
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019774sub majorVersion($)
19775{
19776 my $V = $_[0];
19777 return 0 if(not $V);
19778 my @VParts = split(/\./, $V);
19779 return $VParts[0];
19780}
19781
19782sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019783{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019784 my ($V1, $V2) = @_;
19785 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019786 my @V1Parts = split(/\./, $V1);
19787 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019788 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19789 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019790 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19791 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19792 }
19793 return -1 if($#V1Parts < $#V2Parts);
19794 return 1 if($#V1Parts > $#V2Parts);
19795 return 0;
19796}
19797
19798sub read_ABI_Dump($$)
19799{
19800 my ($LibVersion, $Path) = @_;
19801 return if(not $LibVersion or not -e $Path);
19802 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019803 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 { # input *.abi
19805 $FilePath = $Path;
19806 }
19807 else
19808 { # input *.abi.tar.gz
19809 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019810 if(not isDump_U($FilePath)) {
19811 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019813 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019814
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019815 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019816
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019817 my $Line = readLineNum($FilePath, 0);
19818 if($Line=~/xml/)
19819 { # XML format
19820 loadModule("XmlDump");
19821 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019822 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019823 else
19824 { # Perl Data::Dumper format (default)
19825 open(DUMP, $FilePath);
19826 local $/ = undef;
19827 my $Content = <DUMP>;
19828 close(DUMP);
19829
19830 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19831 { # remove temp file
19832 unlink($FilePath);
19833 }
19834 if($Content!~/};\s*\Z/) {
19835 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19836 }
19837 $ABI = eval($Content);
19838 if(not $ABI) {
19839 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019841 }
19842 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019843 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019844 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019845 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019846 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019847 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019848 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019849 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019850 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019851
19852 if($ABI->{"ABI_DUMP_VERSION"})
19853 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019854 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019855 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019856 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019857 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019858 }
19859 else
19860 { # support for old ABI dumps
19861 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019862 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019863 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019864 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019865 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019866
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019867 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019868 {
19869 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 +040019870 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019871
19872 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19873 { # DWARF ABI Dump
19874 $UseConv_Real{$LibVersion}{"P"} = 1;
19875 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19876
19877 $UsedDump{$LibVersion}{"DWARF"} = 1;
19878
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030019879 if(not $TargetComponent_Opt)
19880 {
19881 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
19882 $TargetComponent = "module";
19883 }
19884 else {
19885 $TargetComponent = "object";
19886 }
19887 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019888 }
19889
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019890 if(not checkDump($LibVersion, "2.11"))
19891 { # old ABI dumps
19892 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019893 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019894 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019895 { # ABI dump created with --binary option
19896 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19897 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019898 else
19899 { # default
19900 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19901 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019902
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019903 if(defined $ABI->{"Mode"}
19904 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019905 { # --ext option
19906 $ExtendedCheck = 1;
19907 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019908 if($ABI->{"Extra"}) {
19909 $ExtraDump = 1;
19910 }
19911
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019912 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019913 {
19914 $UsedDump{$LibVersion}{"L"} = $Lang;
19915 setLanguage($LibVersion, $Lang);
19916 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019917 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019918 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019919 }
19920 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019921 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019922 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019923 if(not $TInfo)
19924 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019925 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019926 }
19927 my %Tid_TDid = ();
19928 foreach my $TDid (keys(%{$TInfo}))
19929 {
19930 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19931 {
19932 $MAX_ID = $Tid if($Tid>$MAX_ID);
19933 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019934 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019935 }
19936 }
19937 my %NewID = ();
19938 foreach my $Tid (keys(%Tid_TDid))
19939 {
19940 my @TDids = keys(%{$Tid_TDid{$Tid}});
19941 if($#TDids>=1)
19942 {
19943 foreach my $TDid (@TDids)
19944 {
19945 if($TDid) {
19946 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19947 }
19948 else
19949 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019950 my $ID = ++$MAX_ID;
19951
19952 $NewID{$TDid}{$Tid} = $ID;
19953 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19954 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019955 }
19956 }
19957 }
19958 else
19959 {
19960 my $TDid = $TDids[0];
19961 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19962 }
19963 }
19964 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19965 {
19966 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19967 if(defined $Info{"BaseType"})
19968 {
19969 my $Bid = $Info{"BaseType"}{"Tid"};
19970 my $BDid = $Info{"BaseType"}{"TDid"};
19971 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019972 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019973 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19974 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19975 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019976 }
19977 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019979 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019980 read_Machine_DumpInfo($ABI, $LibVersion);
19981 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019982 if(not $SymbolInfo{$LibVersion})
19983 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019984 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019985 }
19986 if(not keys(%{$SymbolInfo{$LibVersion}}))
19987 { # validation of old-version dumps
19988 if(not $ExtendedCheck) {
19989 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19990 }
19991 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019992 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019993 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019994 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019995 else
19996 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019997 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019998 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019999 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020000 }
20001 if(not $DepSymbols)
20002 { # Cannot reconstruct DepSymbols. This may result in false
20003 # positives if the old dump is for library 2. Not a problem if
20004 # old dumps are only from old libraries.
20005 $DepSymbols = {};
20006 }
20007 foreach my $Symbol (keys(%{$DepSymbols})) {
20008 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020010 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020011 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020012
20013 if(my $V = $TargetVersion{$LibVersion}) {
20014 $Descriptor{$LibVersion}{"Version"} = $V;
20015 }
20016 else {
20017 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20018 }
20019
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020020 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020021 if(not $SkipTypes{$LibVersion})
20022 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020023 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020024 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020026 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020027 { # if not defined by -skip-symbols option
20028 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20029 if(not $SkipSymbols{$LibVersion})
20030 { # support for old dumps
20031 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20032 }
20033 if(not $SkipSymbols{$LibVersion})
20034 { # support for old dumps
20035 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20036 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020037 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020038 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020039
20040 if(not $TargetHeaders{$LibVersion})
20041 { # if not defined by -headers-list option
20042 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20043 }
20044
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020045 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020046 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020047 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020048 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020049 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020050 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020051
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020052 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020053 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020054
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020055 if(not checkDump($LibVersion, "2.10.1")
20056 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020057 { # support for old ABI dumps: added target headers
20058 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020059 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020060 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020061
20062 if(not $ABI->{"PublicABI"})
20063 {
20064 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20065 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20066 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020068 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020069 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020070 if(defined $ABI->{"GccConstants"})
20071 { # 3.0
20072 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20073 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20074 }
20075 }
20076
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020077 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020078 if(not $NestedNameSpaces{$LibVersion})
20079 { # support for old dumps
20080 # Cannot reconstruct NameSpaces. This may affect design
20081 # of the compatibility report.
20082 $NestedNameSpaces{$LibVersion} = {};
20083 }
20084 # target system type
20085 # needed to adopt HTML report
20086 if(not $DumpSystem)
20087 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020088 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020089 }
20090 # recreate environment
20091 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20092 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020093 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020094 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020095 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20096 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020097 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020098 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020099 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020100 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20101 {
20102 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20103 setLanguage($LibVersion, "C++");
20104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020105 }
20106 }
20107 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020108 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20109 {
20110 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20111 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20112 }
20113 }
20114
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020115 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020116 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020117 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020118 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020119 {
20120 if(not $Symbol_Library{$LibVersion}{$MnglName}
20121 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20122 push(@VFunc, $MnglName);
20123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020124 }
20125 }
20126 translateSymbols(@VFunc, $LibVersion);
20127 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020128 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20129
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020130 if(not checkDump($LibVersion, "3.0"))
20131 { # support for old ABI dumps
20132 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20133 {
20134 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20135 {
20136 if(ref($BaseType) eq "HASH") {
20137 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20138 }
20139 }
20140 }
20141 }
20142
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020143 if(not checkDump($LibVersion, "3.2"))
20144 { # support for old ABI dumps
20145 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20146 {
20147 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20148 {
20149 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20150 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20151 }
20152 }
20153 }
20154
20155 # repair target headers list
20156 delete($TargetHeaders{$LibVersion});
20157 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020158 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20159 }
20160 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20161 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020162 }
20163
20164 # non-target constants from anon enums
20165 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20166 {
20167 if(not $ExtraDump
20168 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20169 {
20170 delete($Constants{$LibVersion}{$Name});
20171 }
20172 }
20173 }
20174
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020175 if(not checkDump($LibVersion, "2.20"))
20176 { # support for old ABI dumps
20177 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20178 {
20179 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20180
20181 if($TType=~/Struct|Union|Enum|Typedef/)
20182 { # repair complex types first
20183 next;
20184 }
20185
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020186 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020187 {
20188 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20189 if($BType=~/Struct|Union|Enum/i)
20190 {
20191 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20192 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20193 }
20194 }
20195 }
20196 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20197 {
20198 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20199 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20200 if($TType=~/Struct|Union|Enum/) {
20201 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20202 }
20203 }
20204 }
20205
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020206 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020207 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020208 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20209 { # support for old ABI dumps < 2.0 (ACC 1.22)
20210 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20211 {
20212 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20213 {
20214 if($Access ne "public") {
20215 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20216 }
20217 }
20218 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20219 }
20220 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20221 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020222 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20223 { # support for old ABI dumps
20224 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20225 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020226 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20227 { # DWARF ABI Dumps
20228 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20229 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020230 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20231 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20232 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020233 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20234 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020235 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020236 foreach (keys(%{$TInfo{"Base"}})) {
20237 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020239 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020240 if($TInfo{"Type"} eq "MethodPtr")
20241 {
20242 if(defined $TInfo{"Param"})
20243 { # support for old ABI dumps <= 1.17
20244 if(not defined $TInfo{"Param"}{"0"})
20245 {
20246 my $Max = keys(%{$TInfo{"Param"}});
20247 foreach my $Pos (1 .. $Max) {
20248 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20249 }
20250 delete($TInfo{"Param"}{$Max});
20251 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20252 }
20253 }
20254 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020255 if($TInfo{"BaseType"} eq $TypeId)
20256 { # fix ABI dump
20257 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20258 }
20259 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020260 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020261 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020263 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20264 if(not $BName)
20265 { # broken type
20266 next;
20267 }
20268 if($TInfo{"Name"} eq $BName)
20269 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020270 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020271 next;
20272 }
20273 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20274 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020275 }
20276 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020277 }
20278 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20279 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020280 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020281 }
20282 }
20283
20284 if(not checkDump($LibVersion, "2.15"))
20285 { # support for old ABI dumps
20286 my %Dups = ();
20287 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20288 {
20289 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020290 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020291 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20292 { # remove template decls
20293 delete($SymbolInfo{$LibVersion}{$InfoId});
20294 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020296 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020297 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20298 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020299 { # templates
20300 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020301 }
20302 }
20303 }
20304
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020305 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20306 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020307 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20308 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20309 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20310 { # support for old ABI dumps (< 3.1)
20311 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20312 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20313 { # add "this" first parameter
20314 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20315 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20316
20317 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20318 {
20319 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20320 foreach my $Pos (reverse(0 .. $#Pos)) {
20321 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20322 }
20323 }
20324 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20325 }
20326 }
20327
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020328 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20329 { # ABI dumps have no mangled names for C-functions
20330 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20331 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020332 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20333 { # support for old ABI dumps
20334 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20335 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020336 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20337 { # DWARF ABI Dumps
20338 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20339 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020340 }
20341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020342 $Descriptor{$LibVersion}{"Dump"} = 1;
20343}
20344
20345sub read_Machine_DumpInfo($$)
20346{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020347 my ($ABI, $LibVersion) = @_;
20348 if($ABI->{"Arch"}) {
20349 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020350 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020351 if($ABI->{"WordSize"}) {
20352 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020353 }
20354 else
20355 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020356 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020357 }
20358 if(not $WORD_SIZE{$LibVersion})
20359 { # support for old dumps (<1.23)
20360 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20361 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020362 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020363 }
20364 else
20365 {
20366 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020367 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020369 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20370 { # any "pointer"-type
20371 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020372 last;
20373 }
20374 }
20375 if($PSize)
20376 { # a pointer type size
20377 $WORD_SIZE{$LibVersion} = $PSize;
20378 }
20379 else {
20380 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20381 }
20382 }
20383 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020384 if($ABI->{"GccVersion"}) {
20385 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020386 }
20387}
20388
20389sub read_Libs_DumpInfo($$)
20390{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020391 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020392 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20393 if(not $Library_Symbol{$LibVersion})
20394 { # support for old dumps
20395 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020397 if(keys(%{$Library_Symbol{$LibVersion}})
20398 and not $DumpAPI) {
20399 $Descriptor{$LibVersion}{"Libs"} = "OK";
20400 }
20401}
20402
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020403sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020404{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020405 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020406
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020407 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020408 and not $DumpAPI) {
20409 $Descriptor{$LibVersion}{"Headers"} = "OK";
20410 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020411 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020412 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020413 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020414 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020415 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020416
20417 if(keys(%{$ABI->{"Sources"}})
20418 and not $DumpAPI) {
20419 $Descriptor{$LibVersion}{"Sources"} = "OK";
20420 }
20421 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020422 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020423 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20424 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020426}
20427
20428sub find_libs($$$)
20429{
20430 my ($Path, $Type, $MaxDepth) = @_;
20431 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020432 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020433}
20434
20435sub createDescriptor($$)
20436{
20437 my ($LibVersion, $Path) = @_;
20438 if(not $LibVersion or not $Path
20439 or not -e $Path) {
20440 return "";
20441 }
20442 if(-d $Path)
20443 { # directory with headers files and shared objects
20444 return "
20445 <version>
20446 ".$TargetVersion{$LibVersion}."
20447 </version>
20448
20449 <headers>
20450 $Path
20451 </headers>
20452
20453 <libs>
20454 $Path
20455 </libs>";
20456 }
20457 else
20458 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020459 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020460 { # standard XML-descriptor
20461 return readFile($Path);
20462 }
20463 elsif(is_header($Path, 2, $LibVersion))
20464 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020465 $CheckHeadersOnly = 1;
20466
20467 if($LibVersion==1) {
20468 $TargetVersion{$LibVersion} = "X";
20469 }
20470
20471 if($LibVersion==2) {
20472 $TargetVersion{$LibVersion} = "Y";
20473 }
20474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020475 return "
20476 <version>
20477 ".$TargetVersion{$LibVersion}."
20478 </version>
20479
20480 <headers>
20481 $Path
20482 </headers>
20483
20484 <libs>
20485 none
20486 </libs>";
20487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020488 else
20489 { # standard XML-descriptor
20490 return readFile($Path);
20491 }
20492 }
20493}
20494
20495sub detect_lib_default_paths()
20496{
20497 my %LPaths = ();
20498 if($OSgroup eq "bsd")
20499 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020500 if(my $LdConfig = get_CmdPath("ldconfig"))
20501 {
20502 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20503 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020504 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20505 {
20506 my $Name = "lib".$1;
20507 if(not defined $LPaths{$Name}) {
20508 $LPaths{$Name} = $2;
20509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020510 }
20511 }
20512 }
20513 else {
20514 printMsg("WARNING", "can't find ldconfig");
20515 }
20516 }
20517 else
20518 {
20519 if(my $LdConfig = get_CmdPath("ldconfig"))
20520 {
20521 if($SystemRoot and $OSgroup eq "linux")
20522 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20523 if(-e $SystemRoot."/etc/ld.so.conf") {
20524 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20525 }
20526 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020527 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20528 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020529 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20530 {
20531 my ($Name, $Path) = ($1, $2);
20532 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020533 if(not defined $LPaths{$Name})
20534 { # get first element from the list of available paths
20535
20536 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20537 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20538 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20539
20540 $LPaths{$Name} = $Path;
20541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020542 }
20543 }
20544 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020545 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020546 printMsg("WARNING", "can't find ldconfig");
20547 }
20548 }
20549 return \%LPaths;
20550}
20551
20552sub detect_bin_default_paths()
20553{
20554 my $EnvPaths = $ENV{"PATH"};
20555 if($OSgroup eq "beos") {
20556 $EnvPaths.=":".$ENV{"BETOOLS"};
20557 }
20558 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020559 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020560 {
20561 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020562 next if(not $Path);
20563 if($SystemRoot
20564 and $Path=~/\A\Q$SystemRoot\E\//)
20565 { # do NOT use binaries from target system
20566 next;
20567 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020568 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020569 }
20570}
20571
20572sub detect_inc_default_paths()
20573{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020574 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020575 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020576 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020577 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020578 next if(index($Line, "/cc1plus ")!=-1);
20579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020580 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20581 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020582 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020583 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020584 if(index($Path, "c++")!=-1
20585 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020587 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020588 if(not defined $MAIN_CPP_DIR
20589 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20590 $MAIN_CPP_DIR = $Path;
20591 }
20592 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020593 elsif(index($Path, "gcc")!=-1) {
20594 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020595 }
20596 else
20597 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020598 if($Path=~/local[\/\\]+include/)
20599 { # local paths
20600 next;
20601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020602 if($SystemRoot
20603 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20604 { # The GCC include path for user headers is not a part of the system root
20605 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20606 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20607 next;
20608 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020609 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020610 }
20611 }
20612 }
20613 unlink("$TMP_DIR/empty.h");
20614 return %DPaths;
20615}
20616
20617sub detect_default_paths($)
20618{
20619 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20620 my $Search = $_[0];
20621 if($Search!~/inc/) {
20622 $HSearch = 0;
20623 }
20624 if($Search!~/lib/) {
20625 $LSearch = 0;
20626 }
20627 if($Search!~/bin/) {
20628 $BSearch = 0;
20629 }
20630 if($Search!~/gcc/) {
20631 $GSearch = 0;
20632 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020633 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020634 { # <search_headers> section of the XML descriptor
20635 # do NOT search for systems headers
20636 $HSearch = 0;
20637 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020638 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020639 { # <search_libs> section of the XML descriptor
20640 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020641 $LSearch = 0;
20642 }
20643 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20644 { # additional search paths
20645 next if($Type eq "include" and not $HSearch);
20646 next if($Type eq "lib" and not $LSearch);
20647 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020648 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020649 }
20650 if($OSgroup ne "windows")
20651 { # unix-like
20652 foreach my $Type ("include", "lib", "bin")
20653 { # automatic detection of system "devel" directories
20654 next if($Type eq "include" and not $HSearch);
20655 next if($Type eq "lib" and not $LSearch);
20656 next if($Type eq "bin" and not $BSearch);
20657 my ($UsrDir, $RootDir) = ("/usr", "/");
20658 if($SystemRoot and $Type ne "bin")
20659 { # 1. search for target headers and libraries
20660 # 2. use host commands: ldconfig, readelf, etc.
20661 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20662 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020663 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020664 if(-d $RootDir."/".$Type)
20665 { # if "/lib" is symbolic link
20666 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020667 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020668 }
20669 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020670 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020671 }
20672 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020673 if(-d $UsrDir)
20674 {
20675 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020676 if(-d $UsrDir."/".$Type)
20677 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020678 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020679 }
20680 }
20681 }
20682 }
20683 if($BSearch)
20684 {
20685 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020686 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020687 }
20688 # check environment variables
20689 if($OSgroup eq "beos")
20690 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020691 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020692 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020693 if($_ eq ".") {
20694 next;
20695 }
20696 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20697 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20698 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020699 }
20700 }
20701 if($HSearch)
20702 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020703 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20704 split(/:|;/, $ENV{"BEINCLUDES"})
20705 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020706 }
20707 if($LSearch)
20708 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020709 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20710 split(/:|;/, $ENV{"BELIBRARIES"}),
20711 split(/:|;/, $ENV{"LIBRARY_PATH"})
20712 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020713 }
20714 }
20715 if($LSearch)
20716 { # using linker to get system paths
20717 if(my $LPaths = detect_lib_default_paths())
20718 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020719 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720 foreach my $Name (keys(%{$LPaths}))
20721 {
20722 if($SystemRoot
20723 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20724 { # wrong ldconfig configuration
20725 # check your <sysroot>/etc/ld.so.conf
20726 next;
20727 }
20728 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020729 if(my $Dir = get_dirname($LPaths->{$Name})) {
20730 $Dirs{$Dir} = 1;
20731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020733 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020734 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020735 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020736 }
20737 if($BSearch)
20738 {
20739 if($CrossGcc)
20740 { # --cross-gcc=arm-linux-gcc
20741 if(-e $CrossGcc)
20742 { # absolute or relative path
20743 $GCC_PATH = get_abs_path($CrossGcc);
20744 }
20745 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20746 { # command name
20747 $GCC_PATH = $CrossGcc;
20748 }
20749 else {
20750 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20751 }
20752 if($GCC_PATH=~/\s/) {
20753 $GCC_PATH = "\"".$GCC_PATH."\"";
20754 }
20755 }
20756 }
20757 if($GSearch)
20758 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020759 if(not $CrossGcc)
20760 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761 $GCC_PATH = get_CmdPath("gcc");
20762 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020763 if(not $GCC_PATH)
20764 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020765 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020766 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020767 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020768 { # select the latest version
20769 @GCCs = sort {$b cmp $a} @GCCs;
20770 if(check_gcc($GCCs[0], "3"))
20771 {
20772 $GCC_PATH = $GCCs[0];
20773 last;
20774 }
20775 }
20776 }
20777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020778 if(not $GCC_PATH) {
20779 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20780 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020781
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020782 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020783 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020784 my $GccTarget = get_dumpmachine($GCC_PATH);
20785
20786 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020787 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020788 $OStarget = "linux";
20789 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020790 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020791 elsif($GccTarget=~/symbian/)
20792 {
20793 $OStarget = "symbian";
20794 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20795 }
20796
20797 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20798
20799 # check GCC version
20800 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20801 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20802 # introduced in 4.8
20803 # fixed in 4.8.3
20804 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20805 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020806 }
20807 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020808 else {
20809 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020810 }
20811 }
20812 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020813 {
20814 # GCC standard paths
20815 if($GCC_PATH and not $NoStdInc)
20816 {
20817 my %DPaths = detect_inc_default_paths();
20818 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20819 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20820 @DefaultIncPaths = @{$DPaths{"Inc"}};
20821 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20822 }
20823
20824 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020825 my $IncPath = "/usr/include";
20826 if($SystemRoot) {
20827 $IncPath = $SystemRoot.$IncPath;
20828 }
20829 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020830 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020831 }
20832 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020833
20834 if($ExtraInfo)
20835 {
20836 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20837 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020839}
20840
20841sub getLIB_EXT($)
20842{
20843 my $Target = $_[0];
20844 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20845 return $Ext;
20846 }
20847 return $OS_LibExt{$LIB_TYPE}{"default"};
20848}
20849
20850sub getAR_EXT($)
20851{
20852 my $Target = $_[0];
20853 if(my $Ext = $OS_Archive{$Target}) {
20854 return $Ext;
20855 }
20856 return $OS_Archive{"default"};
20857}
20858
20859sub get_dumpversion($)
20860{
20861 my $Cmd = $_[0];
20862 return "" if(not $Cmd);
20863 if($Cache{"get_dumpversion"}{$Cmd}) {
20864 return $Cache{"get_dumpversion"}{$Cmd};
20865 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020866 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020867 chomp($V);
20868 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20869}
20870
20871sub get_dumpmachine($)
20872{
20873 my $Cmd = $_[0];
20874 return "" if(not $Cmd);
20875 if($Cache{"get_dumpmachine"}{$Cmd}) {
20876 return $Cache{"get_dumpmachine"}{$Cmd};
20877 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020878 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020879 chomp($Machine);
20880 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20881}
20882
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020883sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020884{
20885 my $Cmd = $_[0];
20886 return "" if(not $Cmd);
20887 my @Options = (
20888 "--version",
20889 "-help"
20890 );
20891 foreach my $Opt (@Options)
20892 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020893 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894 if($Info) {
20895 return 1;
20896 }
20897 }
20898 return 0;
20899}
20900
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020901sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020902{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020903 my ($Cmd, $ReqVer) = @_;
20904 return 0 if(not $Cmd or not $ReqVer);
20905 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20906 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020907 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020908 if(my $GccVer = get_dumpversion($Cmd))
20909 {
20910 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20911 if(cmpVersions($GccVer, $ReqVer)>=0) {
20912 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20913 }
20914 }
20915 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020916}
20917
20918sub get_depth($)
20919{
20920 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020921 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922 }
20923 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20924}
20925
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020926sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020927{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020928 return if($Cache{"registerGccHeaders"}); # this function should be called once
20929
20930 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020932 my @Headers = cmd_find($Path,"f");
20933 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20934 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020935 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020936 my $FileName = get_filename($HPath);
20937 if(not defined $DefaultGccHeader{$FileName})
20938 { # skip duplicated
20939 $DefaultGccHeader{$FileName} = $HPath;
20940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020941 }
20942 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020943 $Cache{"registerGccHeaders"} = 1;
20944}
20945
20946sub registerCppHeaders()
20947{
20948 return if($Cache{"registerCppHeaders"}); # this function should be called once
20949
20950 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020951 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952 my @Headers = cmd_find($CppDir,"f");
20953 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20954 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020956 my $FileName = get_filename($Path);
20957 if(not defined $DefaultCppHeader{$FileName})
20958 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 $DefaultCppHeader{$FileName} = $Path;
20960 }
20961 }
20962 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020963 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020964}
20965
20966sub parse_libname($$$)
20967{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020968 return "" if(not $_[0]);
20969 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20970 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020971 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020972 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20973}
20974
20975sub parse_libname_I($$$)
20976{
20977 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020978
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 if($Target eq "symbian") {
20980 return parse_libname_symbian($Name, $Type);
20981 }
20982 elsif($Target eq "windows") {
20983 return parse_libname_windows($Name, $Type);
20984 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020985
20986 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020988 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020989 { # libSDL-1.2.so.0.7.1
20990 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020991 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020992 if($Type eq "name")
20993 { # libSDL-1.2
20994 # libwbxml2
20995 return $2;
20996 }
20997 elsif($Type eq "name+ext")
20998 { # libSDL-1.2.so
20999 # libwbxml2.so
21000 return $1;
21001 }
21002 elsif($Type eq "version")
21003 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021004 if(defined $7
21005 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 { # 0.7.1
21007 return $7;
21008 }
21009 else
21010 { # libc-2.5.so (=>2.5 version)
21011 my $MV = $5;
21012 $MV=~s/\A[\-\_]+//g;
21013 return $MV;
21014 }
21015 }
21016 elsif($Type eq "short")
21017 { # libSDL
21018 # libwbxml2
21019 return $3;
21020 }
21021 elsif($Type eq "shortest")
21022 { # SDL
21023 # wbxml
21024 return shortest_name($3);
21025 }
21026 }
21027 return "";# error
21028}
21029
21030sub parse_libname_symbian($$)
21031{
21032 my ($Name, $Type) = @_;
21033 my $Ext = getLIB_EXT("symbian");
21034 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21035 { # libpthread{00010001}.dso
21036 if($Type eq "name")
21037 { # libpthread{00010001}
21038 return $2;
21039 }
21040 elsif($Type eq "name+ext")
21041 { # libpthread{00010001}.dso
21042 return $1;
21043 }
21044 elsif($Type eq "version")
21045 { # 00010001
21046 my $V = $4;
21047 $V=~s/\{(.+)\}/$1/;
21048 return $V;
21049 }
21050 elsif($Type eq "short")
21051 { # libpthread
21052 return $3;
21053 }
21054 elsif($Type eq "shortest")
21055 { # pthread
21056 return shortest_name($3);
21057 }
21058 }
21059 return "";# error
21060}
21061
21062sub parse_libname_windows($$)
21063{
21064 my ($Name, $Type) = @_;
21065 my $Ext = getLIB_EXT("windows");
21066 if($Name=~/((.+?)\.$Ext)\Z/)
21067 { # netapi32.dll
21068 if($Type eq "name")
21069 { # netapi32
21070 return $2;
21071 }
21072 elsif($Type eq "name+ext")
21073 { # netapi32.dll
21074 return $1;
21075 }
21076 elsif($Type eq "version")
21077 { # DLL version embedded
21078 # at binary-level
21079 return "";
21080 }
21081 elsif($Type eq "short")
21082 { # netapi32
21083 return $2;
21084 }
21085 elsif($Type eq "shortest")
21086 { # netapi
21087 return shortest_name($2);
21088 }
21089 }
21090 return "";# error
21091}
21092
21093sub shortest_name($)
21094{
21095 my $Name = $_[0];
21096 # remove prefix
21097 $Name=~s/\A(lib|open)//;
21098 # remove suffix
21099 $Name=~s/[\W\d_]+\Z//i;
21100 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21101 return $Name;
21102}
21103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021104sub createSymbolsList($$$$$)
21105{
21106 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021107
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021108 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021109 prepareSymbols(1);
21110
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021111 my %SymbolHeaderLib = ();
21112 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021114 # Get List
21115 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21116 {
21117 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021118 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021119 next;
21120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021121 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021122 { # skip other symbols
21123 next;
21124 }
21125 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21126 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021127 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021128 next;
21129 }
21130 my $DyLib = $Symbol_Library{1}{$Symbol};
21131 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021132 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021133 next;
21134 }
21135 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21136 $Total+=1;
21137 }
21138 # Draw List
21139 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21140 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21141 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21142 {
21143 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21144 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021145 my %NS_Symbol = ();
21146 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021147 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021148 }
21149 foreach my $NameSpace (sort keys(%NS_Symbol))
21150 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021151 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021152 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21153 foreach my $Symbol (@SortedInterfaces)
21154 {
21155 my $SubReport = "";
21156 my $Signature = get_Signature($Symbol, 1);
21157 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021158 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 }
21160 if($Symbol=~/\A(_Z|\?)/)
21161 {
21162 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021163 $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 +040021164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021165 else {
21166 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21167 }
21168 }
21169 else
21170 {
21171 if($Signature) {
21172 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21173 }
21174 else {
21175 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21176 }
21177 }
21178 $SYMBOLS_LIST .= $SubReport;
21179 }
21180 }
21181 $SYMBOLS_LIST .= "<br/>\n";
21182 }
21183 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021184 # clear info
21185 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21186 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21187 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21188 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021189 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021190 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021191 my $CssStyles = readModule("Styles", "SymbolsList.css");
21192 my $JScripts = readModule("Scripts", "Sections.js");
21193 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021194 my $Title = "$LName: public symbols";
21195 my $Keywords = "$LName, API, symbols";
21196 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021197 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021198 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021199 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021200 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021201 writeFile($SaveTo, $SYMBOLS_LIST);
21202}
21203
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021204sub add_target_libs($)
21205{
21206 foreach (@{$_[0]}) {
21207 $TargetLibs{$_} = 1;
21208 }
21209}
21210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021211sub is_target_lib($)
21212{
21213 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021214 if(not $LName) {
21215 return 0;
21216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 if($TargetLibraryName
21218 and $LName!~/\Q$TargetLibraryName\E/) {
21219 return 0;
21220 }
21221 if(keys(%TargetLibs)
21222 and not $TargetLibs{$LName}
21223 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21224 return 0;
21225 }
21226 return 1;
21227}
21228
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021229sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021230{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021231 my ($H, $V) = @_;
21232 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021233 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021234 if($TargetHeaders{$V}{$H}) {
21235 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021236 }
21237 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021238 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021239}
21240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021241sub readLibs($)
21242{
21243 my $LibVersion = $_[0];
21244 if($OStarget eq "windows")
21245 { # dumpbin.exe will crash
21246 # without VS Environment
21247 check_win32_env();
21248 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021249 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021250 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021251 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252}
21253
21254sub dump_sorting($)
21255{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021256 my $Hash = $_[0];
21257 return [] if(not $Hash);
21258 my @Keys = keys(%{$Hash});
21259 return [] if($#Keys<0);
21260 if($Keys[0]=~/\A\d+\Z/)
21261 { # numbers
21262 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021264 else
21265 { # strings
21266 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021267 }
21268}
21269
21270sub printMsg($$)
21271{
21272 my ($Type, $Msg) = @_;
21273 if($Type!~/\AINFO/) {
21274 $Msg = $Type.": ".$Msg;
21275 }
21276 if($Type!~/_C\Z/) {
21277 $Msg .= "\n";
21278 }
21279 if($Quiet)
21280 { # --quiet option
21281 appendFile($COMMON_LOG_PATH, $Msg);
21282 }
21283 else
21284 {
21285 if($Type eq "ERROR") {
21286 print STDERR $Msg;
21287 }
21288 else {
21289 print $Msg;
21290 }
21291 }
21292}
21293
21294sub exitStatus($$)
21295{
21296 my ($Code, $Msg) = @_;
21297 printMsg("ERROR", $Msg);
21298 exit($ERROR_CODE{$Code});
21299}
21300
21301sub exitReport()
21302{ # the tool has run without any errors
21303 printReport();
21304 if($COMPILE_ERRORS)
21305 { # errors in headers may add false positives/negatives
21306 exit($ERROR_CODE{"Compile_Error"});
21307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021308 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21309 { # --binary
21310 exit($ERROR_CODE{"Incompatible"});
21311 }
21312 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21313 { # --source
21314 exit($ERROR_CODE{"Incompatible"});
21315 }
21316 elsif($RESULT{"Source"}{"Problems"}
21317 or $RESULT{"Binary"}{"Problems"})
21318 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021319 exit($ERROR_CODE{"Incompatible"});
21320 }
21321 else {
21322 exit($ERROR_CODE{"Compatible"});
21323 }
21324}
21325
21326sub readRules($)
21327{
21328 my $Kind = $_[0];
21329 if(not -f $RULES_PATH{$Kind}) {
21330 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21331 }
21332 my $Content = readFile($RULES_PATH{$Kind});
21333 while(my $Rule = parseTag(\$Content, "rule"))
21334 {
21335 my $RId = parseTag(\$Rule, "id");
21336 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21337 foreach my $Prop (@Properties) {
21338 if(my $Value = parseTag(\$Rule, lc($Prop)))
21339 {
21340 $Value=~s/\n[ ]*//;
21341 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21342 }
21343 }
21344 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21345 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21346 }
21347 else {
21348 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21349 }
21350 }
21351}
21352
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021353sub getReportPath($)
21354{
21355 my $Level = $_[0];
21356 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21357 if($Level eq "Binary")
21358 {
21359 if($BinaryReportPath)
21360 { # --bin-report-path
21361 return $BinaryReportPath;
21362 }
21363 elsif($OutputReportPath)
21364 { # --report-path
21365 return $OutputReportPath;
21366 }
21367 else
21368 { # default
21369 return $Dir."/abi_compat_report.$ReportFormat";
21370 }
21371 }
21372 elsif($Level eq "Source")
21373 {
21374 if($SourceReportPath)
21375 { # --src-report-path
21376 return $SourceReportPath;
21377 }
21378 elsif($OutputReportPath)
21379 { # --report-path
21380 return $OutputReportPath;
21381 }
21382 else
21383 { # default
21384 return $Dir."/src_compat_report.$ReportFormat";
21385 }
21386 }
21387 else
21388 {
21389 if($OutputReportPath)
21390 { # --report-path
21391 return $OutputReportPath;
21392 }
21393 else
21394 { # default
21395 return $Dir."/compat_report.$ReportFormat";
21396 }
21397 }
21398}
21399
21400sub printStatMsg($)
21401{
21402 my $Level = $_[0];
21403 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21404}
21405
21406sub listAffected($)
21407{
21408 my $Level = $_[0];
21409 my $List = "";
21410 foreach (keys(%{$TotalAffected{$Level}}))
21411 {
21412 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21413 { # skip "Low"-severity problems
21414 next;
21415 }
21416 $List .= "$_\n";
21417 }
21418 my $Dir = get_dirname(getReportPath($Level));
21419 if($Level eq "Binary") {
21420 writeFile($Dir."/abi_affected.txt", $List);
21421 }
21422 elsif($Level eq "Source") {
21423 writeFile($Dir."/src_affected.txt", $List);
21424 }
21425}
21426
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021427sub printReport()
21428{
21429 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021430 createReport();
21431 if($JoinReport or $DoubleReport)
21432 {
21433 if($RESULT{"Binary"}{"Problems"}
21434 or $RESULT{"Source"}{"Problems"}) {
21435 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021436 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021437 else {
21438 printMsg("INFO", "result: COMPATIBLE");
21439 }
21440 printStatMsg("Binary");
21441 printStatMsg("Source");
21442 if($ListAffected)
21443 { # --list-affected
21444 listAffected("Binary");
21445 listAffected("Source");
21446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021447 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021448 elsif($BinaryOnly)
21449 {
21450 if($RESULT{"Binary"}{"Problems"}) {
21451 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21452 }
21453 else {
21454 printMsg("INFO", "result: COMPATIBLE");
21455 }
21456 printStatMsg("Binary");
21457 if($ListAffected)
21458 { # --list-affected
21459 listAffected("Binary");
21460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021461 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021462 elsif($SourceOnly)
21463 {
21464 if($RESULT{"Source"}{"Problems"}) {
21465 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21466 }
21467 else {
21468 printMsg("INFO", "result: COMPATIBLE");
21469 }
21470 printStatMsg("Source");
21471 if($ListAffected)
21472 { # --list-affected
21473 listAffected("Source");
21474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021475 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021476 if($StdOut)
21477 {
21478 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021479 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021480 printMsg("INFO", "compatibility report has been generated to stdout");
21481 }
21482 else
21483 { # default
21484 printMsg("INFO", "compatibility reports have been generated to stdout");
21485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021486 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021487 else
21488 {
21489 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021490 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021491 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21492 }
21493 elsif($DoubleReport)
21494 { # default
21495 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21496 }
21497 elsif($BinaryOnly)
21498 { # --binary
21499 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21500 }
21501 elsif($SourceOnly)
21502 { # --source
21503 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021505 }
21506}
21507
21508sub check_win32_env()
21509{
21510 if(not $ENV{"DevEnvDir"}
21511 or not $ENV{"LIB"}) {
21512 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21513 }
21514}
21515
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021516sub diffSets($$)
21517{
21518 my ($S1, $S2) = @_;
21519 my @SK1 = keys(%{$S1});
21520 my @SK2 = keys(%{$S2});
21521 if($#SK1!=$#SK2) {
21522 return 1;
21523 }
21524 foreach my $K1 (@SK1)
21525 {
21526 if(not defined $S2->{$K1}) {
21527 return 1;
21528 }
21529 }
21530 return 0;
21531}
21532
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021533sub defaultDumpPath($$)
21534{
21535 my ($N, $V) = @_;
21536 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21537}
21538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021539sub create_ABI_Dump()
21540{
21541 if(not -e $DumpAPI) {
21542 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21543 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021544
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021545 if(isDump($DumpAPI)) {
21546 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021547 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021548 else {
21549 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021550 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021551
21552 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021553 { # set to default: N
21554 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021555 }
21556
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021557 initLogging(1);
21558 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021559
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021560 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021561 if($OutputDumpPath)
21562 { # user defined path
21563 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021564 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021565 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21566
21567 if(not $Archive and not $StdOut)
21568 { # check archive utilities
21569 if($OSgroup eq "windows")
21570 { # using zip
21571 my $ZipCmd = get_CmdPath("zip");
21572 if(not $ZipCmd) {
21573 exitStatus("Not_Found", "can't find \"zip\"");
21574 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021575 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021576 else
21577 { # using tar and gzip
21578 my $TarCmd = get_CmdPath("tar");
21579 if(not $TarCmd) {
21580 exitStatus("Not_Found", "can't find \"tar\"");
21581 }
21582 my $GzipCmd = get_CmdPath("gzip");
21583 if(not $GzipCmd) {
21584 exitStatus("Not_Found", "can't find \"gzip\"");
21585 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021586 }
21587 }
21588
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021589 if(not $Descriptor{1}{"Dump"})
21590 {
21591 if(not $CheckHeadersOnly) {
21592 readLibs(1);
21593 }
21594 if($CheckHeadersOnly) {
21595 setLanguage(1, "C++");
21596 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021597 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021598 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021599 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021600 if(not $Descriptor{1}{"Dump"})
21601 {
21602 if($Descriptor{1}{"Headers"}) {
21603 readHeaders(1);
21604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021605 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021606 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021607 if(not keys(%{$SymbolInfo{1}}))
21608 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021609 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021610 {
21611 if($CheckHeadersOnly) {
21612 exitStatus("Empty_Set", "the set of public symbols is empty");
21613 }
21614 else {
21615 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21616 }
21617 }
21618 }
21619 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021620 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021621 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21622 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021623 if($ExtraDump)
21624 { # add unmangled names to the ABI dump
21625 my @Names = ();
21626 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21627 {
21628 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21629 push(@Names, $MnglName);
21630 }
21631 }
21632 translateSymbols(@Names, 1);
21633 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21634 {
21635 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21636 {
21637 if(my $Unmangled = $tr_name{$MnglName})
21638 {
21639 if($MnglName ne $Unmangled) {
21640 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21641 }
21642 }
21643 }
21644 }
21645 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021646
21647 my %GccConstants = (); # built-in GCC constants
21648 foreach my $Name (keys(%{$Constants{1}}))
21649 {
21650 if(not defined $Constants{1}{$Name}{"Header"})
21651 {
21652 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21653 delete($Constants{1}{$Name});
21654 }
21655 }
21656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021657 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021658 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021659 "TypeInfo" => $TypeInfo{1},
21660 "SymbolInfo" => $SymbolInfo{1},
21661 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021662 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021663 "SymbolVersion" => $SymVer{1},
21664 "LibraryVersion" => $Descriptor{1}{"Version"},
21665 "LibraryName" => $TargetLibraryName,
21666 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021667 "SkipTypes" => $SkipTypes{1},
21668 "SkipSymbols" => $SkipSymbols{1},
21669 "SkipNameSpaces" => $SkipNameSpaces{1},
21670 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021671 "Headers" => \%HeadersInfo,
21672 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021673 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021674 "NameSpaces" => $NestedNameSpaces{1},
21675 "Target" => $OStarget,
21676 "Arch" => getArch(1),
21677 "WordSize" => $WORD_SIZE{1},
21678 "GccVersion" => get_dumpversion($GCC_PATH),
21679 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21680 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21681 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021682 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021683 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021684 }
21685 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021686 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021688 if($ExtendedCheck)
21689 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021690 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021691 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021692 if($BinaryOnly)
21693 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021694 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021695 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021696 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021697 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021698 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021699 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21700 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021701 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021702
21703 my $ABI_DUMP = "";
21704 if($UseXML)
21705 {
21706 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021707 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021708 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021709 else
21710 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021711 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021713 if($StdOut)
21714 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021715 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021716 printMsg("INFO", "ABI dump has been generated to stdout");
21717 return;
21718 }
21719 else
21720 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021721 my ($DDir, $DName) = separate_path($DumpPath);
21722 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021723 if(not $Archive) {
21724 $DPath = $DumpPath;
21725 }
21726
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021727 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021728
21729 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021730 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021731 close(DUMP);
21732
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021733 if(not -s $DPath) {
21734 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21735 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021736 if($Archive) {
21737 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021738 }
21739
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021740 if($OutputDumpPath) {
21741 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021742 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021743 else {
21744 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21745 }
21746 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 +040021747 }
21748}
21749
21750sub quickEmptyReports()
21751{ # Quick "empty" reports
21752 # 4 times faster than merging equal dumps
21753 # NOTE: the dump contains the "LibraryVersion" attribute
21754 # if you change the version, then your dump will be different
21755 # OVERCOME: use -v1 and v2 options for comparing dumps
21756 # and don't change version in the XML descriptor (and dumps)
21757 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21758 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21759 {
21760 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21761 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21762 if($FilePath1 and $FilePath2)
21763 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021764 my $Line = readLineNum($FilePath1, 0);
21765 if($Line=~/xml/)
21766 { # XML format
21767 # is not supported yet
21768 return;
21769 }
21770
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021771 local $/ = undef;
21772
21773 open(DUMP1, $FilePath1);
21774 my $Content1 = <DUMP1>;
21775 close(DUMP1);
21776
21777 open(DUMP2, $FilePath2);
21778 my $Content2 = <DUMP2>;
21779 close(DUMP2);
21780
21781 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021782 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021783 # clean memory
21784 undef $Content2;
21785
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021786 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021787 my $ABIdump = eval($Content1);
21788
21789 # clean memory
21790 undef $Content1;
21791
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021792 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021793 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 +040021794 }
21795 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021796 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021797 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21798 }
21799 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021800 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021801 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21802 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021803 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021804 read_Libs_DumpInfo($ABIdump, 1);
21805 read_Machine_DumpInfo($ABIdump, 1);
21806 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021807
21808 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21809 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21810
21811 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21812 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21813
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021814 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21815 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21816 exitReport();
21817 }
21818 }
21819 }
21820}
21821
21822sub initLogging($)
21823{
21824 my $LibVersion = $_[0];
21825 # create log directory
21826 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21827 if($OutputLogPath{$LibVersion})
21828 { # user-defined by -log-path option
21829 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21830 }
21831 if($LogMode ne "n") {
21832 mkpath($LOG_DIR);
21833 }
21834 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021835 if($Debug)
21836 { # debug directory
21837 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021838
21839 if(not $ExtraInfo)
21840 { # enable --extra-info
21841 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021843 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021844 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021845}
21846
21847sub writeLog($$)
21848{
21849 my ($LibVersion, $Msg) = @_;
21850 if($LogMode ne "n") {
21851 appendFile($LOG_PATH{$LibVersion}, $Msg);
21852 }
21853}
21854
21855sub resetLogging($)
21856{
21857 my $LibVersion = $_[0];
21858 if($LogMode!~/a|n/)
21859 { # remove old log
21860 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021861 if($Debug) {
21862 rmtree($DEBUG_PATH{$LibVersion});
21863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021864 }
21865}
21866
21867sub printErrorLog($)
21868{
21869 my $LibVersion = $_[0];
21870 if($LogMode ne "n") {
21871 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21872 }
21873}
21874
21875sub isDump($)
21876{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021877 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21878 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021879 return $1;
21880 }
21881 return 0;
21882}
21883
21884sub isDump_U($)
21885{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021886 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021887 return $1;
21888 }
21889 return 0;
21890}
21891
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021892sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021893{
21894 # read input XML descriptors or ABI dumps
21895 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021896 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021897 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021898 if(not -e $Descriptor{1}{"Path"}) {
21899 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021900 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021901
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021902 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021903 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021904 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021905 if(not -e $Descriptor{2}{"Path"}) {
21906 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021907 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021908
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021909 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021910 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021911 and isDump($Descriptor{2}{"Path"}))
21912 { # optimization: equal ABI dumps
21913 quickEmptyReports();
21914 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021916 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021917
21918 if(isDump($Descriptor{1}{"Path"})) {
21919 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021920 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021921 else {
21922 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21923 }
21924
21925 if(isDump($Descriptor{2}{"Path"})) {
21926 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21927 }
21928 else {
21929 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021930 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021931
21932 if(not $Descriptor{1}{"Version"})
21933 { # set to default: X
21934 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021935 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021936 }
21937
21938 if(not $Descriptor{2}{"Version"})
21939 { # set to default: Y
21940 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021941 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021942 }
21943
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030021944 if(not $UsedDump{1}{"V"}) {
21945 initLogging(1);
21946 }
21947
21948 if(not $UsedDump{2}{"V"}) {
21949 initLogging(2);
21950 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021951
21952 # check input data
21953 if(not $Descriptor{1}{"Headers"}) {
21954 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021955 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021956 if(not $Descriptor{2}{"Headers"}) {
21957 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021958 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021959
21960 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021961 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021962 if(not $Descriptor{1}{"Libs"}) {
21963 exitStatus("Error", "can't find libraries info in descriptor d1");
21964 }
21965 if(not $Descriptor{2}{"Libs"}) {
21966 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021967 }
21968 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021969
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021970 if($UseDumps)
21971 { # --use-dumps
21972 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021973 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21974 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021975
21976 unlink($DumpPath1);
21977 unlink($DumpPath2);
21978
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021979 my $pid = fork();
21980 if($pid)
21981 { # dump on two CPU cores
21982 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21983 if($RelativeDirectory{1}) {
21984 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21985 }
21986 if($OutputLogPath{1}) {
21987 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21988 }
21989 if($CrossGcc) {
21990 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21991 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021992 if($Quiet)
21993 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021994 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021995 @PARAMS = (@PARAMS, "-logging-mode", "a");
21996 }
21997 elsif($LogMode and $LogMode ne "w")
21998 { # "w" is default
21999 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022000 }
22001 if($ExtendedCheck) {
22002 @PARAMS = (@PARAMS, "-extended");
22003 }
22004 if($UserLang) {
22005 @PARAMS = (@PARAMS, "-lang", $UserLang);
22006 }
22007 if($TargetVersion{1}) {
22008 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22009 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022010 if($BinaryOnly) {
22011 @PARAMS = (@PARAMS, "-binary");
22012 }
22013 if($SourceOnly) {
22014 @PARAMS = (@PARAMS, "-source");
22015 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022016 if($SortDump) {
22017 @PARAMS = (@PARAMS, "-sort");
22018 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022019 if($DumpFormat and $DumpFormat ne "perl") {
22020 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22021 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022022 if($CheckHeadersOnly) {
22023 @PARAMS = (@PARAMS, "-headers-only");
22024 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022025 if($Debug)
22026 {
22027 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022028 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022030 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022031 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022032 exit(1);
22033 }
22034 }
22035 else
22036 { # child
22037 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22038 if($RelativeDirectory{2}) {
22039 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22040 }
22041 if($OutputLogPath{2}) {
22042 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22043 }
22044 if($CrossGcc) {
22045 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22046 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022047 if($Quiet)
22048 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022049 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022050 @PARAMS = (@PARAMS, "-logging-mode", "a");
22051 }
22052 elsif($LogMode and $LogMode ne "w")
22053 { # "w" is default
22054 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022055 }
22056 if($ExtendedCheck) {
22057 @PARAMS = (@PARAMS, "-extended");
22058 }
22059 if($UserLang) {
22060 @PARAMS = (@PARAMS, "-lang", $UserLang);
22061 }
22062 if($TargetVersion{2}) {
22063 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22064 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022065 if($BinaryOnly) {
22066 @PARAMS = (@PARAMS, "-binary");
22067 }
22068 if($SourceOnly) {
22069 @PARAMS = (@PARAMS, "-source");
22070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022071 if($SortDump) {
22072 @PARAMS = (@PARAMS, "-sort");
22073 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022074 if($DumpFormat and $DumpFormat ne "perl") {
22075 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22076 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022077 if($CheckHeadersOnly) {
22078 @PARAMS = (@PARAMS, "-headers-only");
22079 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022080 if($Debug)
22081 {
22082 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022083 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022085 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022086 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 exit(1);
22088 }
22089 else {
22090 exit(0);
22091 }
22092 }
22093 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022094
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022095 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022096 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22097 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022098 if($TargetTitle ne $TargetLibraryName) {
22099 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022100 }
22101 if($ShowRetVal) {
22102 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22103 }
22104 if($CrossGcc) {
22105 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22106 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022107 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22108 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022109 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022110 }
22111 if($ReportFormat and $ReportFormat ne "html")
22112 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022113 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22114 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022115 if($OutputReportPath) {
22116 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22117 }
22118 if($BinaryReportPath) {
22119 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22120 }
22121 if($SourceReportPath) {
22122 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22123 }
22124 if($LoggingPath) {
22125 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22126 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022127 if($CheckHeadersOnly) {
22128 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22129 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022130 if($BinaryOnly) {
22131 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22132 }
22133 if($SourceOnly) {
22134 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022136 if($Debug)
22137 {
22138 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22139 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022140 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022141 system("perl", $0, @CMP_PARAMS);
22142 exit($?>>8);
22143 }
22144 if(not $Descriptor{1}{"Dump"}
22145 or not $Descriptor{2}{"Dump"})
22146 { # need GCC toolchain to analyze
22147 # header files and libraries
22148 detect_default_paths("inc|lib|gcc");
22149 }
22150 if(not $Descriptor{1}{"Dump"})
22151 {
22152 if(not $CheckHeadersOnly) {
22153 readLibs(1);
22154 }
22155 if($CheckHeadersOnly) {
22156 setLanguage(1, "C++");
22157 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022158 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022159 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022160 }
22161 if(not $Descriptor{2}{"Dump"})
22162 {
22163 if(not $CheckHeadersOnly) {
22164 readLibs(2);
22165 }
22166 if($CheckHeadersOnly) {
22167 setLanguage(2, "C++");
22168 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022169 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022170 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022171 }
22172 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22173 { # support for old ABI dumps
22174 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022175 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022176 {
22177 $WORD_SIZE{1} = $WORD_SIZE{2};
22178 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22179 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022180 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181 {
22182 $WORD_SIZE{2} = $WORD_SIZE{1};
22183 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22184 }
22185 }
22186 elsif(not $WORD_SIZE{1}
22187 and not $WORD_SIZE{2})
22188 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022189 $WORD_SIZE{1} = "4";
22190 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022191 }
22192 if($Descriptor{1}{"Dump"})
22193 { # support for old ABI dumps
22194 prepareTypes(1);
22195 }
22196 if($Descriptor{2}{"Dump"})
22197 { # support for old ABI dumps
22198 prepareTypes(2);
22199 }
22200 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22201 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22202 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022203 # process input data
22204 if($Descriptor{1}{"Headers"}
22205 and not $Descriptor{1}{"Dump"}) {
22206 readHeaders(1);
22207 }
22208 if($Descriptor{2}{"Headers"}
22209 and not $Descriptor{2}{"Dump"}) {
22210 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022211 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022212
22213 # clean memory
22214 %SystemHeaders = ();
22215 %mangled_name_gcc = ();
22216
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022217 prepareSymbols(1);
22218 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022219
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022220 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022221 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022222
22223 # Virtual Tables
22224 registerVTable(1);
22225 registerVTable(2);
22226
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022227 if(not checkDump(1, "1.22")
22228 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022229 { # support for old ABI dumps
22230 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22231 {
22232 if($ClassName=~/</)
22233 { # templates
22234 if(not defined $VirtualTable{1}{$ClassName})
22235 { # synchronize
22236 delete($VirtualTable{2}{$ClassName});
22237 }
22238 }
22239 }
22240 }
22241
22242 registerOverriding(1);
22243 registerOverriding(2);
22244
22245 setVirtFuncPositions(1);
22246 setVirtFuncPositions(2);
22247
22248 # Other
22249 addParamNames(1);
22250 addParamNames(2);
22251
22252 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022253}
22254
22255sub compareAPIs($)
22256{
22257 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022258
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022259 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022260 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022261
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022262 if($Level eq "Binary") {
22263 printMsg("INFO", "comparing ABIs ...");
22264 }
22265 else {
22266 printMsg("INFO", "comparing APIs ...");
22267 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022268
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022269 if($CheckHeadersOnly
22270 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022271 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022272 detectAdded_H($Level);
22273 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022274 }
22275 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022276 { # added/removed in libs
22277 detectAdded($Level);
22278 detectRemoved($Level);
22279 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022280
22281 mergeSymbols($Level);
22282 if(keys(%{$CheckedSymbols{$Level}})) {
22283 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022284 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022285
22286 $Cache{"mergeTypes"} = (); # free memory
22287
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022288 if($CheckHeadersOnly
22289 or $Level eq "Source")
22290 { # added/removed in headers
22291 mergeHeaders($Level);
22292 }
22293 else
22294 { # added/removed in libs
22295 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022296 }
22297}
22298
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022299sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022300{
22301 my %Opts = (
22302 "OStarget"=>$OStarget,
22303 "Debug"=>$Debug,
22304 "Quiet"=>$Quiet,
22305 "LogMode"=>$LogMode,
22306 "CheckHeadersOnly"=>$CheckHeadersOnly,
22307
22308 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022309 "GCC_PATH"=>$GCC_PATH,
22310 "TargetSysInfo"=>$TargetSysInfo,
22311 "CrossPrefix"=>$CrossPrefix,
22312 "TargetLibraryName"=>$TargetLibraryName,
22313 "CrossGcc"=>$CrossGcc,
22314 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022315 "NoStdInc"=>$NoStdInc,
22316
22317 "BinaryOnly" => $BinaryOnly,
22318 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 );
22320 return \%Opts;
22321}
22322
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022323sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022324{
22325 my %CODE_ERROR = reverse(%ERROR_CODE);
22326 return $CODE_ERROR{$_[0]};
22327}
22328
22329sub scenario()
22330{
22331 if($StdOut)
22332 { # enable quiet mode
22333 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022334 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022335 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022336 if(not $LogMode)
22337 { # default
22338 $LogMode = "w";
22339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022340 if($UserLang)
22341 { # --lang=C++
22342 $UserLang = uc($UserLang);
22343 $COMMON_LANGUAGE{1}=$UserLang;
22344 $COMMON_LANGUAGE{2}=$UserLang;
22345 }
22346 if($LoggingPath)
22347 {
22348 $OutputLogPath{1} = $LoggingPath;
22349 $OutputLogPath{2} = $LoggingPath;
22350 if($Quiet) {
22351 $COMMON_LOG_PATH = $LoggingPath;
22352 }
22353 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022354
22355 if($SkipInternalSymbols) {
22356 $SkipInternalSymbols=~s/\*/.*/g;
22357 }
22358
22359 if($SkipInternalTypes) {
22360 $SkipInternalTypes=~s/\*/.*/g;
22361 }
22362
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022363 if($Quick) {
22364 $ADD_TMPL_INSTANCES = 0;
22365 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022366 if($OutputDumpPath)
22367 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022368 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022369 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22370 }
22371 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022372 if($BinaryOnly and $SourceOnly)
22373 { # both --binary and --source
22374 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022375 if(not $CmpSystems)
22376 {
22377 $BinaryOnly = 0;
22378 $SourceOnly = 0;
22379 }
22380
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022381 $DoubleReport = 1;
22382 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022383
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022384 if($OutputReportPath)
22385 { # --report-path
22386 $DoubleReport = 0;
22387 $JoinReport = 1;
22388 }
22389 }
22390 elsif($BinaryOnly or $SourceOnly)
22391 { # --binary or --source
22392 $DoubleReport = 0;
22393 $JoinReport = 0;
22394 }
22395 if($UseXML)
22396 { # --xml option
22397 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022398 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 if($ReportFormat)
22401 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022402 $ReportFormat = lc($ReportFormat);
22403 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022404 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022406 if($ReportFormat eq "htm")
22407 { # HTM == HTML
22408 $ReportFormat = "html";
22409 }
22410 elsif($ReportFormat eq "xml")
22411 { # --report-format=XML equal to --xml
22412 $UseXML = 1;
22413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022414 }
22415 else
22416 { # default: HTML
22417 $ReportFormat = "html";
22418 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022419 if($DumpFormat)
22420 { # validate
22421 $DumpFormat = lc($DumpFormat);
22422 if($DumpFormat!~/\A(xml|perl)\Z/) {
22423 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22424 }
22425 if($DumpFormat eq "xml")
22426 { # --dump-format=XML equal to --xml
22427 $UseXML = 1;
22428 }
22429 }
22430 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022431 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022432 $DumpFormat = "perl";
22433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022434 if($Quiet and $LogMode!~/a|n/)
22435 { # --quiet log
22436 if(-f $COMMON_LOG_PATH) {
22437 unlink($COMMON_LOG_PATH);
22438 }
22439 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022440 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022441 $CheckUndefined = 1;
22442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022443 if($TestTool and $UseDumps)
22444 { # --test && --use-dumps == --test-dump
22445 $TestDump = 1;
22446 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022447 if($Tolerant)
22448 { # enable all
22449 $Tolerance = 1234;
22450 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022451 if($Help)
22452 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022453 HELP_MESSAGE();
22454 exit(0);
22455 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022456 if($InfoMsg)
22457 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022458 INFO_MESSAGE();
22459 exit(0);
22460 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022461 if($ShowVersion)
22462 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022463 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 +040022464 exit(0);
22465 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022466 if($DumpVersion)
22467 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022468 printMsg("INFO", $TOOL_VERSION);
22469 exit(0);
22470 }
22471 if($ExtendedCheck) {
22472 $CheckHeadersOnly = 1;
22473 }
22474 if($SystemRoot_Opt)
22475 { # user defined root
22476 if(not -e $SystemRoot_Opt) {
22477 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22478 }
22479 $SystemRoot = $SystemRoot_Opt;
22480 $SystemRoot=~s/[\/]+\Z//g;
22481 if($SystemRoot) {
22482 $SystemRoot = get_abs_path($SystemRoot);
22483 }
22484 }
22485 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022486
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022487 if($SortDump)
22488 {
22489 $Data::Dumper::Useperl = 1;
22490 $Data::Dumper::Sortkeys = \&dump_sorting;
22491 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022492
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022493 if($TargetLibsPath)
22494 {
22495 if(not -f $TargetLibsPath) {
22496 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22497 }
22498 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22499 $TargetLibs{$Lib} = 1;
22500 }
22501 }
22502 if($TargetHeadersPath)
22503 { # --headers-list
22504 if(not -f $TargetHeadersPath) {
22505 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22506 }
22507 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22508 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022509 $TargetHeaders{1}{get_filename($Header)} = 1;
22510 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022511 }
22512 }
22513 if($TargetHeader)
22514 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022515 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22516 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022517 }
22518 if($TestTool
22519 or $TestDump)
22520 { # --test, --test-dump
22521 detect_default_paths("bin|gcc"); # to compile libs
22522 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022523 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022524 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022525 exit(0);
22526 }
22527 if($DumpSystem)
22528 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022529
22530 if(not $TargetSysInfo) {
22531 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22532 }
22533
22534 if(not -d $TargetSysInfo) {
22535 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22536 }
22537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022538 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022539 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022540 { # system XML descriptor
22541 if(not -f $DumpSystem) {
22542 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22543 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022544
22545 my $SDesc = readFile($DumpSystem);
22546 if(my $RelDir = $RelativeDirectory{1}) {
22547 $SDesc =~ s/{RELPATH}/$RelDir/g;
22548 }
22549
22550 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022551 foreach (@{$Ret->{"Tools"}})
22552 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022553 push_U($SystemPaths{"bin"}, $_);
22554 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022555 }
22556 if($Ret->{"CrossPrefix"}) {
22557 $CrossPrefix = $Ret->{"CrossPrefix"};
22558 }
22559 }
22560 elsif($SystemRoot_Opt)
22561 { # -sysroot "/" option
22562 # default target: /usr/lib, /usr/include
22563 # search libs: /usr/lib and /lib
22564 if(not -e $SystemRoot."/usr/lib") {
22565 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22566 }
22567 if(not -e $SystemRoot."/lib") {
22568 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22569 }
22570 if(not -e $SystemRoot."/usr/include") {
22571 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22572 }
22573 readSystemDescriptor("
22574 <name>
22575 $DumpSystem
22576 </name>
22577 <headers>
22578 $SystemRoot/usr/include
22579 </headers>
22580 <libs>
22581 $SystemRoot/usr/lib
22582 </libs>
22583 <search_libs>
22584 $SystemRoot/lib
22585 </search_libs>");
22586 }
22587 else {
22588 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22589 }
22590 detect_default_paths("bin|gcc"); # to check symbols
22591 if($OStarget eq "windows")
22592 { # to run dumpbin.exe
22593 # and undname.exe
22594 check_win32_env();
22595 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022596 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022597 exit(0);
22598 }
22599 if($CmpSystems)
22600 { # --cmp-systems
22601 detect_default_paths("bin"); # to extract dumps
22602 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022603 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022604 exit(0);
22605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022606 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022607 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022608 }
22609 else
22610 { # validate library name
22611 if($TargetLibraryName=~/[\*\/\\]/) {
22612 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22613 }
22614 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022615 if(not $TargetTitle) {
22616 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022617 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022618
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022619 if($SymbolsListPath)
22620 {
22621 if(not -f $SymbolsListPath) {
22622 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22623 }
22624 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22625 $SymbolsList{$Interface} = 1;
22626 }
22627 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022628 if($TypesListPath)
22629 {
22630 if(not -f $TypesListPath) {
22631 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22632 }
22633 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22634 $TypesList{$Type} = 1;
22635 }
22636 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022637 if($SkipSymbolsListPath)
22638 {
22639 if(not -f $SkipSymbolsListPath) {
22640 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22641 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022642 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22643 {
22644 $SkipSymbols{1}{$Interface} = 1;
22645 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022646 }
22647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022648 if($SkipHeadersPath)
22649 {
22650 if(not -f $SkipHeadersPath) {
22651 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22652 }
22653 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022654 { # register for both versions
22655 $SkipHeadersList{1}{$Path} = 1;
22656 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022657 my ($CPath, $Type) = classifyPath($Path);
22658 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022659 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022660 }
22661 }
22662 if($ParamNamesPath)
22663 {
22664 if(not -f $ParamNamesPath) {
22665 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22666 }
22667 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22668 {
22669 if($Line=~s/\A(\w+)\;//)
22670 {
22671 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022672 if($Line=~/;(\d+);/)
22673 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022674 while($Line=~s/(\d+);(\w+)//) {
22675 $AddIntParams{$Interface}{$1}=$2;
22676 }
22677 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022678 else
22679 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022680 my $Num = 0;
22681 foreach my $Name (split(/;/, $Line)) {
22682 $AddIntParams{$Interface}{$Num++}=$Name;
22683 }
22684 }
22685 }
22686 }
22687 }
22688 if($AppPath)
22689 {
22690 if(not -f $AppPath) {
22691 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22692 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022693
22694 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022695 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022696 $SymbolsList_App{$Interface} = 1;
22697 }
22698 }
22699 if($DumpAPI)
22700 { # --dump-abi
22701 # make an API dump
22702 create_ABI_Dump();
22703 exit($COMPILE_ERRORS);
22704 }
22705 # default: compare APIs
22706 # -d1 <path>
22707 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022708 compareInit();
22709 if($JoinReport or $DoubleReport)
22710 {
22711 compareAPIs("Binary");
22712 compareAPIs("Source");
22713 }
22714 elsif($BinaryOnly) {
22715 compareAPIs("Binary");
22716 }
22717 elsif($SourceOnly) {
22718 compareAPIs("Source");
22719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022720 exitReport();
22721}
22722
22723scenario();