blob: 2c96b8508a6905c4f2dbbc6c9e8eb994931d86cf [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 {
7449 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7450 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7451 $Signature .= "~";
7452 }
7453 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007455 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007456 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 }
7458 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007459 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007460 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007461 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7462 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007464 else
7465 {
7466 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007467 }
7468 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007469 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007470 {
7471 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007472 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007474 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 if(not $ParamTypeName) {
7476 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7477 }
7478 foreach my $Typedef (keys(%ChangedTypedef))
7479 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007480 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7481 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007483 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007484 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7485 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007486 if($ParamName eq "this"
7487 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007488 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007489 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007490 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007491 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007492 }
7493 else {
7494 push(@ParamArray, $ParamTypeName);
7495 }
7496 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007497 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7498 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007499 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007500 }
7501 else
7502 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007503 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007504 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007505 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007507 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007508 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7509 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007510 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007511 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007512 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7513 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007514 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7517 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007518 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007519 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 }
7521 }
7522 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007523 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007524 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525 }
7526 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007527 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007529 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530}
7531
7532sub create_member_decl($$)
7533{
7534 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007535 if($TName=~/\([\*]+\)/)
7536 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7538 return $TName;
7539 }
7540 else
7541 {
7542 my @ArraySizes = ();
7543 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7544 push(@ArraySizes, $1);
7545 }
7546 return $TName." ".$Member.join("", @ArraySizes);
7547 }
7548}
7549
7550sub getFuncType($)
7551{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007552 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7553 {
7554 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7555 {
7556 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7557 {
7558 if($Type eq "method_type") {
7559 return "Method";
7560 }
7561 elsif($Type eq "function_type") {
7562 return "Function";
7563 }
7564 else {
7565 return "Other";
7566 }
7567 }
7568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007570 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007571}
7572
7573sub getFuncTypeId($)
7574{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007575 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7576 {
7577 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7578 return $1;
7579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007580 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007581 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582}
7583
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007584sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007585{ # "._N" or "$_N" in older GCC versions
7586 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007587}
7588
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007589sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007590{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007591 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7592 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007593 }
7594
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007595 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007597 if($_[1] ne "S")
7598 {
7599 $N=~s/\A[ ]+//g;
7600 $N=~s/[ ]+\Z//g;
7601 $N=~s/[ ]{2,}/ /g;
7602 }
7603
7604 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007605
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007606 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007607
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007608 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7609 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007610
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007611 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007612
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007613 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007614
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007615 if($_[1] eq "S")
7616 {
7617 if(index($N, "operator")!=-1) {
7618 $N=~s/\b(operator[ ]*)> >/$1>>/;
7619 }
7620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007621
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007622 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007623}
7624
7625sub get_HeaderDeps($$)
7626{
7627 my ($AbsPath, $LibVersion) = @_;
7628 return () if(not $AbsPath or not $LibVersion);
7629 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7630 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7631 }
7632 my %IncDir = ();
7633 detect_recursive_includes($AbsPath, $LibVersion);
7634 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7635 {
7636 next if(not $HeaderPath);
7637 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7638 my $Dir = get_dirname($HeaderPath);
7639 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7640 {
7641 my $Dep = $Dir;
7642 if($Prefix)
7643 {
7644 if($OSgroup eq "windows")
7645 { # case insensitive seach on windows
7646 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7647 next;
7648 }
7649 }
7650 elsif($OSgroup eq "macos")
7651 { # seach in frameworks
7652 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7653 {
7654 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7655 {# frameworks
7656 my ($HFramework, $HName) = ($1, $2);
7657 $Dep = $HFramework;
7658 }
7659 else
7660 {# mismatch
7661 next;
7662 }
7663 }
7664 }
7665 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7666 { # Linux, FreeBSD
7667 next;
7668 }
7669 }
7670 if(not $Dep)
7671 { # nothing to include
7672 next;
7673 }
7674 if(is_default_include_dir($Dep))
7675 { # included by the compiler
7676 next;
7677 }
7678 if(get_depth($Dep)==1)
7679 { # too short
7680 next;
7681 }
7682 if(isLibcDir($Dep))
7683 { # do NOT include /usr/include/{sys,bits}
7684 next;
7685 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007686 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007687 }
7688 }
7689 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7690 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7691}
7692
7693sub sortIncPaths($$)
7694{
7695 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007696 if(not $ArrRef or $#{$ArrRef}<0) {
7697 return $ArrRef;
7698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007699 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7700 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007701 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007702 return $ArrRef;
7703}
7704
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007705sub sortDeps($$$)
7706{
7707 if($Header_Dependency{$_[2]}{$_[0]}
7708 and not $Header_Dependency{$_[2]}{$_[1]}) {
7709 return 1;
7710 }
7711 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7712 and $Header_Dependency{$_[2]}{$_[1]}) {
7713 return -1;
7714 }
7715 return 0;
7716}
7717
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007718sub join_P($$)
7719{
7720 my $S = "/";
7721 if($OSgroup eq "windows") {
7722 $S = "\\";
7723 }
7724 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007725}
7726
7727sub get_namespace_additions($)
7728{
7729 my $NameSpaces = $_[0];
7730 my ($Additions, $AddNameSpaceId) = ("", 1);
7731 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7732 {
7733 next if($SkipNameSpaces{$Version}{$NS});
7734 next if(not $NS or $NameSpaces->{$NS}==-1);
7735 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7736 next if($NS=~/\A__/i);
7737 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007738 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007739 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7740 my @NS_Parts = split(/::/, $NS);
7741 next if($#NS_Parts==-1);
7742 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7743 foreach my $NS_Part (@NS_Parts)
7744 {
7745 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7746 $TypeDecl_Suffix .= "}";
7747 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007748 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007749 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7750 $Additions.=" $TypeDecl\n $FuncDecl\n";
7751 $AddNameSpaceId+=1;
7752 }
7753 return $Additions;
7754}
7755
7756sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007757{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007758 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007759 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007760 if($Fmt eq "windows")
7761 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007762 $Path=~s/\//\\/g;
7763 $Path=lc($Path);
7764 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007765 else
7766 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007767 $Path=~s/\\/\//g;
7768 }
7769 return $Path;
7770}
7771
7772sub inc_opt($$)
7773{
7774 my ($Path, $Style) = @_;
7775 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007776 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007777 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007778 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007779 return "-I\"".path_format($Path, "unix")."\"";
7780 }
7781 elsif($OSgroup eq "macos"
7782 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007783 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 return "-F".esc(get_dirname($Path));
7785 }
7786 else {
7787 return "-I".esc($Path);
7788 }
7789 }
7790 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007791 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007792 }
7793 return "";
7794}
7795
7796sub platformSpecs($)
7797{
7798 my $LibVersion = $_[0];
7799 my $Arch = getArch($LibVersion);
7800 if($OStarget eq "symbian")
7801 { # options for GCCE compiler
7802 my %Symbian_Opts = map {$_=>1} (
7803 "-D__GCCE__",
7804 "-DUNICODE",
7805 "-fexceptions",
7806 "-D__SYMBIAN32__",
7807 "-D__MARM_INTERWORK__",
7808 "-D_UNICODE",
7809 "-D__S60_50__",
7810 "-D__S60_3X__",
7811 "-D__SERIES60_3X__",
7812 "-D__EPOC32__",
7813 "-D__MARM__",
7814 "-D__EABI__",
7815 "-D__MARM_ARMV5__",
7816 "-D__SUPPORT_CPP_EXCEPTIONS__",
7817 "-march=armv5t",
7818 "-mapcs",
7819 "-mthumb-interwork",
7820 "-DEKA2",
7821 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7822 );
7823 return join(" ", keys(%Symbian_Opts));
7824 }
7825 elsif($OSgroup eq "windows"
7826 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7827 { # add options to MinGW compiler
7828 # to simulate the MSVC compiler
7829 my %MinGW_Opts = map {$_=>1} (
7830 "-D_WIN32",
7831 "-D_STDCALL_SUPPORTED",
7832 "-D__int64=\"long long\"",
7833 "-D__int32=int",
7834 "-D__int16=short",
7835 "-D__int8=char",
7836 "-D__possibly_notnullterminated=\" \"",
7837 "-D__nullterminated=\" \"",
7838 "-D__nullnullterminated=\" \"",
7839 "-D__w64=\" \"",
7840 "-D__ptr32=\" \"",
7841 "-D__ptr64=\" \"",
7842 "-D__forceinline=inline",
7843 "-D__inline=inline",
7844 "-D__uuidof(x)=IID()",
7845 "-D__try=",
7846 "-D__except(x)=",
7847 "-D__declspec(x)=__attribute__((x))",
7848 "-D__pragma(x)=",
7849 "-D_inline=inline",
7850 "-D__forceinline=__inline",
7851 "-D__stdcall=__attribute__((__stdcall__))",
7852 "-D__cdecl=__attribute__((__cdecl__))",
7853 "-D__fastcall=__attribute__((__fastcall__))",
7854 "-D__thiscall=__attribute__((__thiscall__))",
7855 "-D_stdcall=__attribute__((__stdcall__))",
7856 "-D_cdecl=__attribute__((__cdecl__))",
7857 "-D_fastcall=__attribute__((__fastcall__))",
7858 "-D_thiscall=__attribute__((__thiscall__))",
7859 "-DSHSTDAPI_(x)=x",
7860 "-D_MSC_EXTENSIONS",
7861 "-DSECURITY_WIN32",
7862 "-D_MSC_VER=1500",
7863 "-D_USE_DECLSPECS_FOR_SAL",
7864 "-D__noop=\" \"",
7865 "-DDECLSPEC_DEPRECATED=\" \"",
7866 "-D__builtin_alignof(x)=__alignof__(x)",
7867 "-DSORTPP_PASS");
7868 if($Arch eq "x86") {
7869 $MinGW_Opts{"-D_M_IX86=300"}=1;
7870 }
7871 elsif($Arch eq "x86_64") {
7872 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7873 }
7874 elsif($Arch eq "ia64") {
7875 $MinGW_Opts{"-D_M_IA64=300"}=1;
7876 }
7877 return join(" ", keys(%MinGW_Opts));
7878 }
7879 return "";
7880}
7881
7882my %C_Structure = map {$_=>1} (
7883# FIXME: Can't separate union and struct data types before dumping,
7884# so it sometimes cause compilation errors for unknown reason
7885# when trying to declare TYPE* tmp_add_class_N
7886# This is a list of such structures + list of other C structures
7887 "sigval",
7888 "sigevent",
7889 "sigaction",
7890 "sigvec",
7891 "sigstack",
7892 "timeval",
7893 "timezone",
7894 "rusage",
7895 "rlimit",
7896 "wait",
7897 "flock",
7898 "stat",
7899 "_stat",
7900 "stat32",
7901 "_stat32",
7902 "stat64",
7903 "_stat64",
7904 "_stati64",
7905 "if_nameindex",
7906 "usb_device",
7907 "sigaltstack",
7908 "sysinfo",
7909 "timeLocale",
7910 "tcp_debug",
7911 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007912 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007913 "timespec",
7914 "random_data",
7915 "drand48_data",
7916 "_IO_marker",
7917 "_IO_FILE",
7918 "lconv",
7919 "sched_param",
7920 "tm",
7921 "itimerspec",
7922 "_pthread_cleanup_buffer",
7923 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007924 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007925 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007926 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007927 "sigcontext",
7928 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007929 # Mac
7930 "_timex",
7931 "_class_t",
7932 "_category_t",
7933 "_class_ro_t",
7934 "_protocol_t",
7935 "_message_ref_t",
7936 "_super_message_ref_t",
7937 "_ivar_t",
7938 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007939);
7940
7941sub getCompileCmd($$$)
7942{
7943 my ($Path, $Opt, $Inc) = @_;
7944 my $GccCall = $GCC_PATH;
7945 if($Opt) {
7946 $GccCall .= " ".$Opt;
7947 }
7948 $GccCall .= " -x ";
7949 if($OSgroup eq "macos") {
7950 $GccCall .= "objective-";
7951 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007952
7953 if($EMERGENCY_MODE_48)
7954 { # workaround for GCC 4.8 (C only)
7955 $GccCall .= "c++";
7956 }
7957 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007958 { # compile as "C++" header
7959 # to obtain complete dump using GCC 4.0
7960 $GccCall .= "c++-header";
7961 }
7962 else
7963 { # compile as "C++" source
7964 # GCC 3.3 cannot compile headers
7965 $GccCall .= "c++";
7966 }
7967 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007968 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007969 $GccCall .= " ".$Opts;
7970 }
7971 # allow extra qualifications
7972 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007973 $GccCall .= " -fpermissive";
7974 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007975 if($NoStdInc)
7976 {
7977 $GccCall .= " -nostdinc";
7978 $GccCall .= " -nostdinc++";
7979 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007980 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007982 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007983 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007984 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007985 if($Inc)
7986 { # include paths
7987 $GccCall .= " ".$Inc;
7988 }
7989 return $GccCall;
7990}
7991
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007992sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007994 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007995 my %HeaderElems = (
7996 # Types
7997 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007998 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007999 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8000 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008001 "time.h" => ["time_t"],
8002 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008003 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8004 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008005 "stdbool.h" => ["_Bool"],
8006 "rpc/xdr.h" => ["bool_t"],
8007 "in_systm.h" => ["n_long", "n_short"],
8008 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008009 "arpa/inet.h" => ["fw_src", "ip_src"],
8010 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008011 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008012 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008013 );
8014 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008015 foreach (keys(%HeaderElems))
8016 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008017 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008018 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008019 }
8020 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008021 my %Types = ();
8022 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8023 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008024 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008025 }
8026 if(keys(%Types))
8027 {
8028 my %AddHeaders = ();
8029 foreach my $Type (keys(%Types))
8030 {
8031 if(my $Header = $AutoPreamble{$Type})
8032 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008033 if(my $Path = identifyHeader($Header, $LibVersion))
8034 {
8035 if(skipHeader($Path, $LibVersion)) {
8036 next;
8037 }
8038 $Path = path_format($Path, $OSgroup);
8039 $AddHeaders{$Path}{"Type"} = $Type;
8040 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008041 }
8042 }
8043 }
8044 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008045 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008046 }
8047 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008048 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008049}
8050
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008051sub checkCTags($)
8052{
8053 my $Path = $_[0];
8054 if(not $Path) {
8055 return;
8056 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008057 my $CTags = undef;
8058
8059 if($OSgroup eq "bsd")
8060 { # use ectags on BSD
8061 $CTags = get_CmdPath("ectags");
8062 if(not $CTags) {
8063 printMsg("WARNING", "can't find \'ectags\' program");
8064 }
8065 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008066 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008067 $CTags = get_CmdPath("ctags");
8068 }
8069 if(not $CTags)
8070 {
8071 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008072 return;
8073 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008074
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008075 if($OSgroup ne "linux")
8076 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008077 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8078 if($Info!~/exuberant/i)
8079 {
8080 printMsg("WARNING", "incompatible version of \'ctags\' program");
8081 return;
8082 }
8083 }
8084
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008085 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008086 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008087 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008088 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008089 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008090 open(CTAGS, "<", $Out);
8091 while(my $Line = <CTAGS>)
8092 {
8093 chomp($Line);
8094 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008095 if(defined $Intrinsic_Keywords{$Name})
8096 { # noise
8097 next;
8098 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008099 if($Type eq "n")
8100 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008101 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008102 next;
8103 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008104 if(index($Scpe, "struct:")==0) {
8105 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008106 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008107 if(index($Scpe, "namespace:")==0)
8108 {
8109 if($Scpe=~s/\Anamespace://) {
8110 $Name = $Scpe."::".$Name;
8111 }
8112 }
8113 $TUnit_NameSpaces{$Version}{$Name} = 1;
8114 }
8115 elsif($Type eq "p")
8116 {
8117 if(not $Scpe or index($Scpe, "namespace:")==0) {
8118 $TUnit_Funcs{$Version}{$Name} = 1;
8119 }
8120 }
8121 elsif($Type eq "x")
8122 {
8123 if(not $Scpe or index($Scpe, "namespace:")==0) {
8124 $TUnit_Vars{$Version}{$Name} = 1;
8125 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008126 }
8127 }
8128 close(CTAGS);
8129}
8130
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008131sub preChange($$)
8132{
8133 my ($HeaderPath, $IncStr) = @_;
8134
8135 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8136 my $Content = undef;
8137
8138 if($OStarget eq "windows"
8139 and get_dumpmachine($GCC_PATH)=~/mingw/i
8140 and $MinGWMode{$Version}!=-1)
8141 { # modify headers to compile by MinGW
8142 if(not $Content)
8143 { # preprocessing
8144 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8145 }
8146 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8147 { # __asm { ... }
8148 $MinGWMode{$Version}=1;
8149 }
8150 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8151 { # comments after preprocessing
8152 $MinGWMode{$Version}=1;
8153 }
8154 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8155 { # 0xffui8
8156 $MinGWMode{$Version}=1;
8157 }
8158
8159 if($MinGWMode{$Version}) {
8160 printMsg("INFO", "Using MinGW compatibility mode");
8161 }
8162 }
8163
8164 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8165 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8166 { # rename C++ keywords in C code
8167 # disable this code by -cpp-compatible option
8168 if(not $Content)
8169 { # preprocessing
8170 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8171 }
8172 my $RegExp_C = join("|", keys(%CppKeywords_C));
8173 my $RegExp_F = join("|", keys(%CppKeywords_F));
8174 my $RegExp_O = join("|", keys(%CppKeywords_O));
8175
8176 my $Detected = undef;
8177
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008178 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 +04008179 { # MATCH:
8180 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008181 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008182 # unsigned private: 8;
8183 # DO NOT MATCH:
8184 # #pragma GCC visibility push(default)
8185 $CppMode{$Version} = 1;
8186 $Detected = "$1$2$3$4" if(not defined $Detected);
8187 }
8188 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8189 { # MATCH:
8190 # int delete(...);
8191 # int explicit(...);
8192 # DO NOT MATCH:
8193 # void operator delete(...)
8194 $CppMode{$Version} = 1;
8195 $Detected = "$1$2$3" if(not defined $Detected);
8196 }
8197 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8198 { # MATCH:
8199 # int bool;
8200 # DO NOT MATCH:
8201 # bool X;
8202 # return *this;
8203 # throw;
8204 $CppMode{$Version} = 1;
8205 $Detected = "$1$2$3" if(not defined $Detected);
8206 }
8207 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8208 { # MATCH:
8209 # int operator(...);
8210 # DO NOT MATCH:
8211 # int operator()(...);
8212 $CppMode{$Version} = 1;
8213 $Detected = "$1$2$3" if(not defined $Detected);
8214 }
8215 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8216 { # MATCH:
8217 # int foo(int operator);
8218 # int foo(int operator, int other);
8219 # DO NOT MATCH:
8220 # int operator,(...);
8221 $CppMode{$Version} = 1;
8222 $Detected = "$1$2$3" if(not defined $Detected);
8223 }
8224 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8225 { # MATCH:
8226 # int foo(gboolean *bool);
8227 # DO NOT MATCH:
8228 # void setTabEnabled(int index, bool);
8229 $CppMode{$Version} = 1;
8230 $Detected = "$1$2$3" if(not defined $Detected);
8231 }
8232 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8233 { # MATCH:
8234 # int foo(int* this);
8235 # int bar(int this);
8236 # int baz(int throw);
8237 # DO NOT MATCH:
8238 # foo(X, this);
8239 $CppMode{$Version} = 1;
8240 $Detected = "$1$2$3$4" if(not defined $Detected);
8241 }
8242 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8243 { # MATCH:
8244 # struct template {...};
8245 # extern template foo(...);
8246 $CppMode{$Version} = 1;
8247 $Detected = "$1$2" if(not defined $Detected);
8248 }
8249
8250 if($CppMode{$Version} == 1)
8251 {
8252 if($Debug)
8253 {
8254 $Detected=~s/\A\s+//g;
8255 printMsg("INFO", "Detected code: \"$Detected\"");
8256 }
8257 }
8258
8259 # remove typedef enum NAME NAME;
8260 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8261 my $N = 0;
8262 while($N<=$#FwdTypedefs-1)
8263 {
8264 my $S = $FwdTypedefs[$N];
8265 if($S eq $FwdTypedefs[$N+1])
8266 {
8267 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008268 $CppMode{$Version} = 1;
8269
8270 if($Debug) {
8271 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8272 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008273 }
8274 $N+=2;
8275 }
8276
8277 if($CppMode{$Version}==1) {
8278 printMsg("INFO", "Using C++ compatibility mode");
8279 }
8280 }
8281
8282 if($CppMode{$Version}==1
8283 or $MinGWMode{$Version}==1)
8284 {
8285 my $IPath = $TMP_DIR."/dump$Version.i";
8286 writeFile($IPath, $Content);
8287 return $IPath;
8288 }
8289
8290 return undef;
8291}
8292
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008293sub getDump()
8294{
8295 if(not $GCC_PATH) {
8296 exitStatus("Error", "internal error - GCC path is not set");
8297 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008298
8299 my @Headers = keys(%{$Registered_Headers{$Version}});
8300 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8301
8302 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8303
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008304 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008305 my $HeaderPath = $TmpHeaderPath;
8306
8307 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008308 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008309 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8310 {
8311 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008312 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008313 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008314 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008315 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8316 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008317 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008318 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008319 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008320 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8321 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008323 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008324 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008325
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008326 if($ExtraInfo)
8327 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008328 if($IncludeString) {
8329 writeFile($ExtraInfo."/include-string", $IncludeString);
8330 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008331 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8332 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008333
8334 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8335 {
8336 my $REDIR = "";
8337 foreach my $P1 (sort @Redirects) {
8338 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8339 }
8340 writeFile($ExtraInfo."/include-redirect", $REDIR);
8341 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008342 }
8343
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008344 if(not keys(%{$TargetHeaders{$Version}}))
8345 { # Target headers
8346 addTargetHeaders($Version);
8347 }
8348
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008349 # clean memory
8350 %RecursiveIncludes = ();
8351 %Header_Include_Prefix = ();
8352 %Header_Includes = ();
8353
8354 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008355 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008356 delete($Cache{"detect_header_includes"});
8357 delete($Cache{"selectSystemHeader"});
8358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008359 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008360 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8361 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008362
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008363 if($ExtraInfo)
8364 { # extra information for other tools
8365 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8366 }
8367
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008368 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008369 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008370 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008371
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008372 if($COMMON_LANGUAGE{$Version} eq "C++") {
8373 checkCTags($Pre);
8374 }
8375
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008376 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8377 { # try to correct the preprocessor output
8378 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008379 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008381 if($COMMON_LANGUAGE{$Version} eq "C++")
8382 { # add classes and namespaces to the dump
8383 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008384 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008385 or $MinGWMode{$Version}==1) {
8386 $CHdump .= " -fpreprocessed";
8387 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008388 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008389 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008390 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008391 chdir($ORIG_DIR);
8392 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8393 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008394 my $Content = readFile($ClassDump);
8395 foreach my $ClassInfo (split(/\n\n/, $Content))
8396 {
8397 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8398 {
8399 my $CName = $1;
8400 next if($CName=~/\A(__|_objc_|_opaque_)/);
8401 $TUnit_NameSpaces{$Version}{$CName} = -1;
8402 if($CName=~/\A[\w:]+\Z/)
8403 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008404 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008405 }
8406 if($CName=~/(\w[\w:]*)::/)
8407 { # namespaces
8408 my $NS = $1;
8409 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8410 $TUnit_NameSpaces{$Version}{$NS} = 1;
8411 }
8412 }
8413 }
8414 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8415 { # read v-tables (advanced approach)
8416 my ($CName, $VTable) = ($1, $2);
8417 $ClassVTable_Content{$Version}{$CName} = $VTable;
8418 }
8419 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008420 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8421 { # add user-defined namespaces
8422 $TUnit_NameSpaces{$Version}{$NS} = 1;
8423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008424 if($Debug)
8425 { # debug mode
8426 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008427 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008428 }
8429 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008430 }
8431
8432 # add namespaces and classes
8433 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8434 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008435 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008436 }
8437 # some GCC versions don't include class methods to the TU dump by default
8438 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008439 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008440 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8441 {
8442 next if($C_Structure{$CName});
8443 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008444 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008445 if(not $Force and $GCC_44
8446 and $OSgroup eq "linux")
8447 { # optimization for linux with GCC >= 4.4
8448 # disable this code by -force option
8449 if(index($CName, "::")!=-1)
8450 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008451 next;
8452 }
8453 }
8454 else
8455 {
8456 if($CName=~/\A(.+)::[^:]+\Z/
8457 and $TUnit_Classes{$Version}{$1})
8458 { # classes inside other classes
8459 next;
8460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008461 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008462 if(defined $TUnit_Funcs{$Version}{$CName})
8463 { # the same name for a function and type
8464 next;
8465 }
8466 if(defined $TUnit_Vars{$Version}{$CName})
8467 { # the same name for a variable and type
8468 next;
8469 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008470 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8471 }
8472 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008473 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008474 }
8475 }
8476 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8477 # create TU dump
8478 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008479 if($UserLang eq "C") {
8480 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8481 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008482 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008483 or $MinGWMode{$Version}==1) {
8484 $TUdump .= " -fpreprocessed";
8485 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008486 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008487 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8488 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008489 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008490 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008491 if($?)
8492 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008493 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008494 { # try to recompile
8495 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008496 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008497 and index($Errors, "c99_")!=-1
8498 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008499 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008500 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008501
8502 if($Debug)
8503 {
8504 # printMsg("INFO", $Errors);
8505 }
8506
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008507 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 resetLogging($Version);
8509 $TMP_DIR = tempdir(CLEANUP=>1);
8510 return getDump();
8511 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008512 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008513 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008514 { # add auto preamble headers and try again
8515 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008516 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008517 foreach my $Num (0 .. $#Headers)
8518 {
8519 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008520 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8521 {
8522 push_U($Include_Preamble{$Version}, $Path);
8523 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008524 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008525 }
8526 resetLogging($Version);
8527 $TMP_DIR = tempdir(CLEANUP=>1);
8528 return getDump();
8529 }
8530 elsif($Cpp0xMode{$Version}!=-1
8531 and ($Errors=~/\Q-std=c++0x\E/
8532 or $Errors=~/is not a class or namespace/))
8533 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008534 if(check_gcc($GCC_PATH, "4.6"))
8535 {
8536 $Cpp0xMode{$Version}=-1;
8537 printMsg("INFO", "Enabling c++0x mode");
8538 resetLogging($Version);
8539 $TMP_DIR = tempdir(CLEANUP=>1);
8540 $CompilerOptions{$Version} .= " -std=c++0x";
8541 return getDump();
8542 }
8543 else {
8544 printMsg("WARNING", "Probably c++0x construction detected");
8545 }
8546
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008547 }
8548 elsif($MinGWMode{$Version}==1)
8549 { # disable MinGW mode and try again
8550 $MinGWMode{$Version}=-1;
8551 resetLogging($Version);
8552 $TMP_DIR = tempdir(CLEANUP=>1);
8553 return getDump();
8554 }
8555 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008556 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008557 else {
8558 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008560 printMsg("ERROR", "some errors occurred when compiling headers");
8561 printErrorLog($Version);
8562 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008563 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008564 }
8565 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008566 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008567 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008568
8569 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8570 return $TUs[0];
8571 }
8572 else
8573 {
8574 my $Msg = "can't compile header(s)";
8575 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8576 $Msg .= "\nDid you install G++?";
8577 }
8578 exitStatus("Cannot_Compile", $Msg);
8579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008580}
8581
8582sub cmd_file($)
8583{
8584 my $Path = $_[0];
8585 return "" if(not $Path or not -e $Path);
8586 if(my $CmdPath = get_CmdPath("file")) {
8587 return `$CmdPath -b \"$Path\"`;
8588 }
8589 return "";
8590}
8591
8592sub getIncString($$)
8593{
8594 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008595 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008596 my $String = "";
8597 foreach (@{$ArrRef}) {
8598 $String .= " ".inc_opt($_, $Style);
8599 }
8600 return $String;
8601}
8602
8603sub getIncPaths(@)
8604{
8605 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008606 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008607 if($INC_PATH_AUTODETECT{$Version})
8608 { # auto-detecting dependencies
8609 my %Includes = ();
8610 foreach my $HPath (@HeaderPaths)
8611 {
8612 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8613 {
8614 if($Skip_Include_Paths{$Version}{$Dir}) {
8615 next;
8616 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008617 if($SystemRoot)
8618 {
8619 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8620 next;
8621 }
8622 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008623 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008624 }
8625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008626 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008627 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008628 }
8629 }
8630 else
8631 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008632 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008633 }
8634 return \@IncPaths;
8635}
8636
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008637sub push_U($@)
8638{ # push unique
8639 if(my $Array = shift @_)
8640 {
8641 if(@_)
8642 {
8643 my %Exist = map {$_=>1} @{$Array};
8644 foreach my $Elem (@_)
8645 {
8646 if(not defined $Exist{$Elem})
8647 {
8648 push(@{$Array}, $Elem);
8649 $Exist{$Elem} = 1;
8650 }
8651 }
8652 }
8653 }
8654}
8655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656sub callPreprocessor($$$)
8657{
8658 my ($Path, $Inc, $LibVersion) = @_;
8659 return "" if(not $Path or not -f $Path);
8660 my $IncludeString=$Inc;
8661 if(not $Inc) {
8662 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8663 }
8664 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008665 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008666 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008667 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008668}
8669
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008670sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008671{ # native "find" is much faster than File::Find (~6x)
8672 # also the File::Find doesn't support --maxdepth N option
8673 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008674 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008675 return () if(not $Path or not -e $Path);
8676 if($OSgroup eq "windows")
8677 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008678 $Path = get_abs_path($Path);
8679 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008680 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008681 if($MaxDepth!=1) {
8682 $Cmd .= " /S";
8683 }
8684 if($Type eq "d") {
8685 $Cmd .= " /AD";
8686 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008687 elsif($Type eq "f") {
8688 $Cmd .= " /A-D";
8689 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008690 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008692 {
8693 if(not $UseRegex)
8694 { # FIXME: how to search file names in MS shell?
8695 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008696 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008697 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008698 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008699 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008700 }
8701 my @AbsPaths = ();
8702 foreach my $File (@Files)
8703 {
8704 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008705 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008706 }
8707 if($Type eq "f" and not -f $File)
8708 { # skip dirs
8709 next;
8710 }
8711 push(@AbsPaths, path_format($File, $OSgroup));
8712 }
8713 if($Type eq "d") {
8714 push(@AbsPaths, $Path);
8715 }
8716 return @AbsPaths;
8717 }
8718 else
8719 {
8720 my $FindCmd = get_CmdPath("find");
8721 if(not $FindCmd) {
8722 exitStatus("Not_Found", "can't find a \"find\" command");
8723 }
8724 $Path = get_abs_path($Path);
8725 if(-d $Path and -l $Path
8726 and $Path!~/\/\Z/)
8727 { # for directories that are symlinks
8728 $Path.="/";
8729 }
8730 my $Cmd = $FindCmd." \"$Path\"";
8731 if($MaxDepth) {
8732 $Cmd .= " -maxdepth $MaxDepth";
8733 }
8734 if($Type) {
8735 $Cmd .= " -type $Type";
8736 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008737 if($Name and not $UseRegex)
8738 { # wildcards
8739 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008740 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008741 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008742 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008743 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8744 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008745 my @Files = split(/\n/, $Res);
8746 if($Name and $UseRegex)
8747 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008748 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008749 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008750 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008751 }
8752}
8753
8754sub unpackDump($)
8755{
8756 my $Path = $_[0];
8757 return "" if(not $Path or not -e $Path);
8758 $Path = get_abs_path($Path);
8759 $Path = path_format($Path, $OSgroup);
8760 my ($Dir, $FileName) = separate_path($Path);
8761 my $UnpackDir = $TMP_DIR."/unpack";
8762 rmtree($UnpackDir);
8763 mkpath($UnpackDir);
8764 if($FileName=~s/\Q.zip\E\Z//g)
8765 { # *.zip
8766 my $UnzipCmd = get_CmdPath("unzip");
8767 if(not $UnzipCmd) {
8768 exitStatus("Not_Found", "can't find \"unzip\" command");
8769 }
8770 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008771 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008773 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008774 }
8775 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008776 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777 if(not @Contents) {
8778 exitStatus("Error", "can't extract \'$Path\'");
8779 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008780 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008782 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008783 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008784 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008785 if($OSgroup eq "windows")
8786 { # -xvzf option is not implemented in tar.exe (2003)
8787 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8788 my $TarCmd = get_CmdPath("tar");
8789 if(not $TarCmd) {
8790 exitStatus("Not_Found", "can't find \"tar\" command");
8791 }
8792 my $GzipCmd = get_CmdPath("gzip");
8793 if(not $GzipCmd) {
8794 exitStatus("Not_Found", "can't find \"gzip\" command");
8795 }
8796 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008797 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008798 if($?) {
8799 exitStatus("Error", "can't extract \'$Path\'");
8800 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008801 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008802 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008803 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008804 }
8805 chdir($ORIG_DIR);
8806 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008807 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008808 if(not @Contents) {
8809 exitStatus("Error", "can't extract \'$Path\'");
8810 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008811 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008812 }
8813 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008814 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008815 my $TarCmd = get_CmdPath("tar");
8816 if(not $TarCmd) {
8817 exitStatus("Not_Found", "can't find \"tar\" command");
8818 }
8819 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008820 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008822 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008823 }
8824 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008825 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008826 if(not @Contents) {
8827 exitStatus("Error", "can't extract \'$Path\'");
8828 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008829 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008830 }
8831 }
8832}
8833
8834sub createArchive($$)
8835{
8836 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008837 if(not $To) {
8838 $To = ".";
8839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 if(not $Path or not -e $Path
8841 or not -d $To) {
8842 return "";
8843 }
8844 my ($From, $Name) = separate_path($Path);
8845 if($OSgroup eq "windows")
8846 { # *.zip
8847 my $ZipCmd = get_CmdPath("zip");
8848 if(not $ZipCmd) {
8849 exitStatus("Not_Found", "can't find \"zip\"");
8850 }
8851 my $Pkg = $To."/".$Name.".zip";
8852 unlink($Pkg);
8853 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008854 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008855 if($?)
8856 { # cannot allocate memory (or other problems with "zip")
8857 unlink($Path);
8858 exitStatus("Error", "can't pack the ABI dump: ".$!);
8859 }
8860 chdir($ORIG_DIR);
8861 unlink($Path);
8862 return $Pkg;
8863 }
8864 else
8865 { # *.tar.gz
8866 my $TarCmd = get_CmdPath("tar");
8867 if(not $TarCmd) {
8868 exitStatus("Not_Found", "can't find \"tar\"");
8869 }
8870 my $GzipCmd = get_CmdPath("gzip");
8871 if(not $GzipCmd) {
8872 exitStatus("Not_Found", "can't find \"gzip\"");
8873 }
8874 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8875 unlink($Pkg);
8876 chdir($From);
8877 system($TarCmd, "-czf", $Pkg, $Name);
8878 if($?)
8879 { # cannot allocate memory (or other problems with "tar")
8880 unlink($Path);
8881 exitStatus("Error", "can't pack the ABI dump: ".$!);
8882 }
8883 chdir($ORIG_DIR);
8884 unlink($Path);
8885 return $To."/".$Name.".tar.gz";
8886 }
8887}
8888
8889sub is_header_file($)
8890{
8891 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8892 return $_[0];
8893 }
8894 return 0;
8895}
8896
8897sub is_not_header($)
8898{
8899 if($_[0]=~/\.\w+\Z/
8900 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8901 return 1;
8902 }
8903 return 0;
8904}
8905
8906sub is_header($$$)
8907{
8908 my ($Header, $UserDefined, $LibVersion) = @_;
8909 return 0 if(-d $Header);
8910 if(-f $Header) {
8911 $Header = get_abs_path($Header);
8912 }
8913 else
8914 {
8915 if(is_abs($Header))
8916 { # incorrect absolute path
8917 return 0;
8918 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008919 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008920 $Header = $HPath;
8921 }
8922 else
8923 { # can't find header
8924 return 0;
8925 }
8926 }
8927 if($Header=~/\.\w+\Z/)
8928 { # have an extension
8929 return is_header_file($Header);
8930 }
8931 else
8932 {
8933 if($UserDefined==2)
8934 { # specified on the command line
8935 if(cmd_file($Header)!~/HTML|XML/i) {
8936 return $Header;
8937 }
8938 }
8939 elsif($UserDefined)
8940 { # specified in the XML-descriptor
8941 # header file without an extension
8942 return $Header;
8943 }
8944 else
8945 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008946 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008947 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008948 { # !~/HTML|XML|shared|dynamic/i
8949 return $Header;
8950 }
8951 }
8952 }
8953 return 0;
8954}
8955
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008956sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008957{
8958 my $LibVersion = $_[0];
8959 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8960 {
8961 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008962 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008963
8964 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8965 detect_recursive_includes($RegHeader, $LibVersion);
8966 }
8967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008968 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8969 {
8970 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008971
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008972 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008973 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8974 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008975 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008976 }
8977 }
8978 }
8979}
8980
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008981sub familiarDirs($$)
8982{
8983 my ($D1, $D2) = @_;
8984 if($D1 eq $D2) {
8985 return 1;
8986 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008987
8988 my $U1 = index($D1, "/usr/");
8989 my $U2 = index($D2, "/usr/");
8990
8991 if($U1==0 and $U2!=0) {
8992 return 0;
8993 }
8994
8995 if($U2==0 and $U1!=0) {
8996 return 0;
8997 }
8998
8999 if(index($D2, $D1."/")==0) {
9000 return 1;
9001 }
9002
9003 # /usr/include/DIR
9004 # /home/user/DIR
9005
9006 my $DL = get_depth($D1);
9007
9008 my @Dirs1 = ($D1);
9009 while($DL - get_depth($D1)<=2
9010 and get_depth($D1)>=4
9011 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9012 push(@Dirs1, $D1);
9013 }
9014
9015 my @Dirs2 = ($D2);
9016 while(get_depth($D2)>=4
9017 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9018 push(@Dirs2, $D2);
9019 }
9020
9021 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009022 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009023 foreach my $P2 (@Dirs2)
9024 {
9025
9026 if($P1 eq $P2) {
9027 return 1;
9028 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009029 }
9030 }
9031 return 0;
9032}
9033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009034sub readHeaders($)
9035{
9036 $Version = $_[0];
9037 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9038 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009039 if($Debug)
9040 { # debug mode
9041 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009042 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009043 }
9044 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009045}
9046
9047sub prepareTypes($)
9048{
9049 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009050 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009051 { # support for old ABI dumps
9052 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009053 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009054 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009055 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9056 if($TName=~/\A(\w+)::(\w+)/) {
9057 my ($P1, $P2) = ($1, $2);
9058 if($P1 eq $P2) {
9059 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009061 else {
9062 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009065 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009066 }
9067 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009068 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009069 { # support for old ABI dumps
9070 # V < 2.5: array size == "number of elements"
9071 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009072 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009073 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009074 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009075 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009076 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009077 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009078 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009079 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009080 $Size *= $Base{"Size"};
9081 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009082 }
9083 else
9084 { # array[] is a pointer
9085 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009086 }
9087 }
9088 }
9089 }
9090 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009091 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009092 { # support for old ABI dumps
9093 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009095 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009096 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009097 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009098 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009099 my %Type = get_Type($TypeId, $LibVersion);
9100 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9101 my %Type2 = get_Type($TypeId_2, $V2);
9102 if($Type{"Size"} ne $Type2{"Size"}) {
9103 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009104 }
9105 }
9106 }
9107 }
9108}
9109
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009110sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009111{
9112 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009113
9114 if(not keys(%{$SymbolInfo{$LibVersion}}))
9115 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009116 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009117 {
9118 if($CheckHeadersOnly) {
9119 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9120 }
9121 else {
9122 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9123 }
9124 }
9125 }
9126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009127 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 if(not checkDump(1, "2.10")
9129 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009130 { # different formats
9131 $Remangle = 1;
9132 }
9133 if($CheckHeadersOnly)
9134 { # different languages
9135 if($UserLang)
9136 { # --lang=LANG for both versions
9137 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9138 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9139 {
9140 if($UserLang eq "C++")
9141 { # remangle symbols
9142 $Remangle = 1;
9143 }
9144 elsif($UserLang eq "C")
9145 { # remove mangling
9146 $Remangle = -1;
9147 }
9148 }
9149 }
9150 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009151
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009152 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009153 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009154 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009155 { # support for old ABI dumps
9156 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9157 {
9158 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9159 {
9160 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9161 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009162 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009163 if(defined $DVal and $DVal ne "")
9164 {
9165 if($TName eq "char") {
9166 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9167 }
9168 elsif($TName eq "bool") {
9169 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9170 }
9171 }
9172 }
9173 }
9174 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009175 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009176 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009177 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9178 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009179 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009180 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9181 # + support for old ABI dumps
9182 next;
9183 }
9184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009185 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009186 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009187 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009188 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009189
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009190 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009191 if(not checkDump(1, "2.12")
9192 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009193 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009194 if($ShortName eq "operator>>")
9195 {
9196 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9197 { # corrected mangling of operator>>
9198 $SRemangle = 1;
9199 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009200 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009201 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9202 {
9203 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9204 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9205 { # corrected mangling of const global data
9206 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9207 # and incorrectly mangled by old ACC versions
9208 $SRemangle = 1;
9209 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009210 }
9211 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009212 if(not $CheckHeadersOnly)
9213 { # support for old ABI dumps
9214 if(not checkDump(1, "2.17")
9215 or not checkDump(2, "2.17"))
9216 {
9217 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9218 {
9219 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9220 {
9221 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9222 {
9223 $MnglName = $ShortName;
9224 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9225 }
9226 }
9227 }
9228 }
9229 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009230 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009231 { # support for old ABI dumps: some symbols are not mangled in old dumps
9232 # mangle both sets of symbols (old and new)
9233 # NOTE: remangling all symbols by the same mangler
9234 if($MnglName=~/\A_ZN(V|)K/)
9235 { # mangling may be incorrect on old ABI dumps
9236 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009237 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009238 }
9239 if($MnglName=~/\A_ZN(K|)V/)
9240 { # mangling may be incorrect on old ABI dumps
9241 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009242 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009243 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009244 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9245 or (not $ClassID and $CheckHeadersOnly)
9246 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9247 { # support for old ABI dumps, GCC >= 4.0
9248 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009249 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009250 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009251 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009252 $MangledNames{$LibVersion}{$MnglName} = 1;
9253 }
9254 }
9255 }
9256 elsif($Remangle==-1)
9257 { # remove mangling
9258 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009259 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009261 if(not $MnglName) {
9262 next;
9263 }
9264 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9265 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009266 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9267
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009269 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009270 { # support for old dumps
9271 # add "Volatile" attribute
9272 if($MnglName=~/_Z(K|)V/) {
9273 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9274 }
9275 }
9276 # symbol and its symlink have same signatures
9277 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009278 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009279 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009280
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009281 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9282 {
9283 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9284 if($SymVer{$LibVersion}{$Alias}) {
9285 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9286 }
9287 }
9288
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009289 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009290 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 }
9292 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9293 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9294 }
9295 if($ExtendedCheck)
9296 { # --ext option
9297 addExtension($LibVersion);
9298 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009299
9300 # clean memory
9301 delete($SymbolInfo{$LibVersion});
9302
9303 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009304 { # detect allocable classes with public exported constructors
9305 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009306 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009307 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009308 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009309 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009310 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9311 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009312 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009313 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009315 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 $AllocableClass{$LibVersion}{$ClassName} = 1;
9317 }
9318 }
9319 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009320 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009322 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009323 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009324 if($CheckHeadersOnly)
9325 {
9326 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9327 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9328 { # all symbols except non-virtual inline
9329 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9330 }
9331 }
9332 else {
9333 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009334 }
9335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009336 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009337 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009338 }
9339 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009340 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009341 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009342 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009343 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009344 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009345 if(defined $Base{"Type"}
9346 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009347 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009348 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009349 if($Name=~/<([^<>\s]+)>/)
9350 {
9351 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9352 $ReturnedClass{$LibVersion}{$Tid} = 1;
9353 }
9354 }
9355 else {
9356 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9357 }
9358 }
9359 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009360 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009363 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009364 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009365 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009366 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009367 if($Base{"Type"}=~/Struct|Class/)
9368 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009369 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009370 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9371 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009372 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009374 }
9375 }
9376 }
9377 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009378
9379 # mapping {short name => symbols}
9380 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009381 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009382 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009383 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009384 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009386 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009388 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9389 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009390 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009391 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 }
9393 }
9394 }
9395 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009396
9397 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009398 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009402 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9403 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009407 $ClassNames{$LibVersion}{$TName} = 1;
9408 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009409 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009410 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9411 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 }
9413 }
9414 }
9415 }
9416 }
9417}
9418
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009419sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009421 my ($Tid, $LibVersion) = @_;
9422 if(not $Tid) {
9423 return $Tid;
9424 }
9425
9426 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9427 {
9428 if($TName_Tid{$LibVersion}{$Name}) {
9429 return $TName_Tid{$LibVersion}{$Name};
9430 }
9431 }
9432
9433 return $Tid;
9434}
9435
9436sub register_SymbolUsage($$$)
9437{
9438 my ($InfoId, $UsedType, $LibVersion) = @_;
9439
9440 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9441 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9442 {
9443 register_TypeUsage($RTid, $UsedType, $LibVersion);
9444 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9445 }
9446 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9447 {
9448 register_TypeUsage($FCid, $UsedType, $LibVersion);
9449 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9450
9451 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9452 { # register "this" pointer
9453 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9454 }
9455 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9456 { # register "this" pointer (const method)
9457 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9458 }
9459 }
9460 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9461 {
9462 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9463 {
9464 register_TypeUsage($PTid, $UsedType, $LibVersion);
9465 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9466 }
9467 }
9468 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9469 {
9470 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9471 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9472 register_TypeUsage($TTid, $UsedType, $LibVersion);
9473 }
9474 }
9475}
9476
9477sub register_TypeUsage($$$)
9478{
9479 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009480 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009481 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009482 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009483 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009484 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009485 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009486 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009487
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009488 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009489 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009490 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009491 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009492 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009493 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9494 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9495 }
9496 }
9497
9498 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9499 {
9500 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009502 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009503 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9504 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009505 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009506 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9507 {
9508 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9509 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009510 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009511 }
9512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009513 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009514 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009515 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009516 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9517 {
9518 register_TypeUsage($MTid, $UsedType, $LibVersion);
9519 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009520 }
9521 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009522 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009523 or $TInfo{"Type"} eq "MethodPtr"
9524 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009525 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009526 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009527 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009529 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009530 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009531 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9532 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009533 }
9534 }
9535 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009536 if($TInfo{"Type"} eq "FieldPtr")
9537 {
9538 if(my $RTid = $TInfo{"Return"}) {
9539 register_TypeUsage($RTid, $UsedType, $LibVersion);
9540 }
9541 if(my $CTid = $TInfo{"Class"}) {
9542 register_TypeUsage($CTid, $UsedType, $LibVersion);
9543 }
9544 }
9545 if($TInfo{"Type"} eq "MethodPtr")
9546 {
9547 if(my $CTid = $TInfo{"Class"}) {
9548 register_TypeUsage($CTid, $UsedType, $LibVersion);
9549 }
9550 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009551 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009552 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009553 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009554 $UsedType->{$TypeId} = 1;
9555 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9556 {
9557 register_TypeUsage($BTid, $UsedType, $LibVersion);
9558 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9559 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009560 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009561 else
9562 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9563 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009564 }
9565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009566}
9567
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009568sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009569{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009570 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9571
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009572 if($Level eq "Dump")
9573 {
9574 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9575 { # TODO: check if this symbol is from
9576 # base classes of other target symbols
9577 return 1;
9578 }
9579 }
9580
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009581 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9582 { # stdc++ interfaces
9583 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009584 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009585
9586 my $Target = 0;
9587 if(my $Header = $SInfo->{"Header"}) {
9588 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9589 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009590 if($ExtendedCheck)
9591 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009592 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009593 $Target = 1;
9594 }
9595 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009596 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009597 {
9598 if($Target)
9599 {
9600 if($Level eq "Dump")
9601 { # dumped
9602 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009603 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009604 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009605 return 1;
9606 }
9607 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009608 else {
9609 return 1;
9610 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009611 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009612 elsif($Level eq "Source")
9613 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009614 return 1;
9615 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009616 elsif($Level eq "Binary")
9617 { # checked
9618 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9619 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9620 return 1;
9621 }
9622 }
9623 }
9624 }
9625 else
9626 { # library is available
9627 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9628 { # exported symbols
9629 return 1;
9630 }
9631 if($Level eq "Dump")
9632 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009633 if($BinaryOnly)
9634 {
9635 if($SInfo->{"Data"})
9636 {
9637 if($Target) {
9638 return 1;
9639 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640 }
9641 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009642 else
9643 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009644 if($Target) {
9645 return 1;
9646 }
9647 }
9648 }
9649 elsif($Level eq "Source")
9650 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009651 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009652 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009653 { # skip LOCAL symbols
9654 if($Target) {
9655 return 1;
9656 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009657 }
9658 }
9659 elsif($Level eq "Binary")
9660 { # checked
9661 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9662 {
9663 if($Target) {
9664 return 1;
9665 }
9666 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009667 }
9668 }
9669 return 0;
9670}
9671
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009672sub cleanDump($)
9673{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009674 my $LibVersion = $_[0];
9675 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9676 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009677 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9678 {
9679 delete($SymbolInfo{$LibVersion}{$InfoId});
9680 next;
9681 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009682 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009683 if(not $MnglName)
9684 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009685 delete($SymbolInfo{$LibVersion}{$InfoId});
9686 next;
9687 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009688 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009689 if(not $ShortName)
9690 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009691 delete($SymbolInfo{$LibVersion}{$InfoId});
9692 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009693 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009694 if($MnglName eq $ShortName)
9695 { # remove duplicate data
9696 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009697 }
9698 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9699 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9700 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009701 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9702 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9703 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009704 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009705 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009706 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009707 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009708 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9709 {
9710 delete($TypeInfo{$LibVersion}{$Tid});
9711 next;
9712 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009713 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009714 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009715 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009716 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9717 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9718 }
9719 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009720 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9721 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9722 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009723 }
9724}
9725
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009726sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009727{
9728 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009729
9730 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9731 {
9732 if(defined $TypeInfo{$LibVersion}{$Dupl})
9733 {
9734 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9735 { # duplicate
9736 return 0;
9737 }
9738 }
9739 }
9740
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009741 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9742
9743 if(isBuiltIn($THeader)) {
9744 return 0;
9745 }
9746
9747 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9748 return 0;
9749 }
9750
9751 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9752 return 0;
9753 }
9754
9755 if(selfTypedef($Tid, $LibVersion)) {
9756 return 0;
9757 }
9758
9759 if(not isTargetType($Tid, $LibVersion)) {
9760 return 0;
9761 }
9762
9763 return 0;
9764}
9765
9766sub isTargetType($$)
9767{
9768 my ($Tid, $LibVersion) = @_;
9769
9770 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9771 { # derived
9772 return 1;
9773 }
9774
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009775 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9776 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009777 if(not is_target_header($THeader, $LibVersion))
9778 { # from target headers
9779 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009780 }
9781 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009782
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009783 if($SkipInternalTypes)
9784 {
9785 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9786 {
9787 return 0;
9788 }
9789 }
9790
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009791 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009792}
9793
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009794sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009795{ # remove unused data types from the ABI dump
9796 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009797
9798 my %UsedType = ();
9799
9800 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009801 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009802 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009803 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009804 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009805 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009806 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009807 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009808 next;
9809 }
9810
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009811 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009812 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009813 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009814 {
9815 my %Tree = ();
9816 register_TypeUsage($Tid, \%Tree, $LibVersion);
9817
9818 my $Tmpl = 0;
9819 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9820 {
9821 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9822 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9823 {
9824 $Tmpl = 1;
9825 last;
9826 }
9827 }
9828 if(not $Tmpl)
9829 {
9830 foreach (keys(%Tree)) {
9831 $UsedType{$_} = 1;
9832 }
9833 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009834 }
9835 }
9836 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009837
9838 my %Delete = ();
9839
9840 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009841 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009842 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009843 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009844 next;
9845 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009846
9847 if($Kind eq "Extra")
9848 {
9849 my %Tree = ();
9850 register_TypeUsage($Tid, \%Tree, $LibVersion);
9851
9852 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9853 {
9854 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9855 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9856 {
9857 $Delete{$Tid} = 1;
9858 last;
9859 }
9860 }
9861 }
9862 else
9863 {
9864 # remove type
9865 delete($TypeInfo{$LibVersion}{$Tid});
9866 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009867 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009868
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009869 if($Kind eq "Extra")
9870 { # remove duplicates
9871 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9872 {
9873 if($UsedType{$Tid})
9874 { # All & Extended
9875 next;
9876 }
9877
9878 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9879
9880 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9881 delete($TypeInfo{$LibVersion}{$Tid});
9882 }
9883 }
9884 }
9885
9886 foreach my $Tid (keys(%Delete))
9887 {
9888 delete($TypeInfo{$LibVersion}{$Tid});
9889 }
9890}
9891
9892sub check_Completeness($$)
9893{
9894 my ($Info, $LibVersion) = @_;
9895
9896 # data types
9897 if(defined $Info->{"Memb"})
9898 {
9899 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9900 {
9901 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9902 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9903 }
9904 }
9905 }
9906 if(defined $Info->{"Base"})
9907 {
9908 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9909 check_TypeInfo($Bid, $LibVersion);
9910 }
9911 }
9912 if(defined $Info->{"BaseType"}) {
9913 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9914 }
9915 if(defined $Info->{"TParam"})
9916 {
9917 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9918 {
9919 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9920 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9921 next;
9922 }
9923 if($TName eq "_BoolType") {
9924 next;
9925 }
9926 if($TName=~/\Asizeof\(/) {
9927 next;
9928 }
9929 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9930 check_TypeInfo($Tid, $LibVersion);
9931 }
9932 else
9933 {
9934 if(defined $Debug) {
9935 printMsg("WARNING", "missed type $TName");
9936 }
9937 }
9938 }
9939 }
9940
9941 # symbols
9942 if(defined $Info->{"Param"})
9943 {
9944 foreach my $Pos (keys(%{$Info->{"Param"}}))
9945 {
9946 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9947 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9948 }
9949 }
9950 }
9951 if(defined $Info->{"Return"}) {
9952 check_TypeInfo($Info->{"Return"}, $LibVersion);
9953 }
9954 if(defined $Info->{"Class"}) {
9955 check_TypeInfo($Info->{"Class"}, $LibVersion);
9956 }
9957}
9958
9959sub check_TypeInfo($$)
9960{
9961 my ($Tid, $LibVersion) = @_;
9962
9963 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9964 return;
9965 }
9966 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9967
9968 if(defined $TypeInfo{$LibVersion}{$Tid})
9969 {
9970 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9971 printMsg("ERROR", "missed type name ($Tid)");
9972 }
9973 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9974 }
9975 else {
9976 printMsg("ERROR", "missed type id $Tid");
9977 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009978}
9979
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009980sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009981{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009982 my ($TypeId, $LibVersion) = @_;
9983 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009984 if($Type{"Type"} eq "Typedef")
9985 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009986 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009987 if($Base{"Type"}=~/Class|Struct/)
9988 {
9989 if($Type{"Name"} eq $Base{"Name"}) {
9990 return 1;
9991 }
9992 elsif($Type{"Name"}=~/::(\w+)\Z/)
9993 {
9994 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9995 { # QPointer<QWidget>::QPointer
9996 return 1;
9997 }
9998 }
9999 }
10000 }
10001 return 0;
10002}
10003
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010004sub addExtension($)
10005{
10006 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010007 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010008 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010009 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010010 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010011 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10012 $TName=~s/\A(struct|union|class|enum) //;
10013 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010014
10015 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10016 "Header" => "extended.h",
10017 "ShortName" => $Symbol,
10018 "MnglName" => $Symbol,
10019 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10020 );
10021
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010022 $ExtendedSymbols{$Symbol} = 1;
10023 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10024 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010025 }
10026 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010027 $ExtendedSymbols{"external_func_0"} = 1;
10028 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10029 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010030}
10031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010032sub findMethod($$$)
10033{
10034 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010035 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010036 {
10037 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10038 return $VirtMethodInClass;
10039 }
10040 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10041 return $VirtMethodInBaseClasses;
10042 }
10043 }
10044 return "";
10045}
10046
10047sub findMethod_Class($$$)
10048{
10049 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010050 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010051 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10052 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10053 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10054 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10055 { # search for interface with the same parameters suffix (overridden)
10056 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10057 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010058 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10059 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010060 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10061 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010062 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10063 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10064 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10065 return $Candidate;
10066 }
10067 }
10068 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010069 else
10070 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10072 return $Candidate;
10073 }
10074 }
10075 }
10076 }
10077 return "";
10078}
10079
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010080sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010081{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010082 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010083 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010084 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010085 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10086 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010087 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010088 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010089 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010090 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10091 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010092 { # pure virtual D2-destructors are marked as "virt" in the dump
10093 # virtual D2-destructors are NOT marked as "virt" in the dump
10094 # both destructors are not presented in the v-table
10095 next;
10096 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010097 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010098 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010100 }
10101}
10102
10103sub registerOverriding($)
10104{
10105 my $LibVersion = $_[0];
10106 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010107 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010108 foreach my $ClassName (@Classes)
10109 {
10110 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10111 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010112 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10113 { # pure virtuals
10114 next;
10115 }
10116 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10117 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010118 {
10119 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10120 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10121 { # both overridden virtual methods
10122 # and implemented pure virtual methods
10123 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10124 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10125 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010127 }
10128 }
10129 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10130 delete($VirtualTable{$LibVersion}{$ClassName});
10131 }
10132 }
10133}
10134
10135sub setVirtFuncPositions($)
10136{
10137 my $LibVersion = $_[0];
10138 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10139 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010140 my ($Num, $Rel) = (1, 0);
10141
10142 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010143 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010144 if($UsedDump{$LibVersion}{"DWARF"}) {
10145 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10146 }
10147 else {
10148 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10149 }
10150 foreach my $VirtFunc (@Funcs)
10151 {
10152 if($UsedDump{$LibVersion}{"DWARF"}) {
10153 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10154 }
10155 else {
10156 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10157 }
10158
10159 # set relative positions
10160 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10161 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10162 { # relative position excluding added and removed virtual functions
10163 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10164 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10165 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010169 }
10170 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010171 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 {
10173 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010175 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176 }
10177 }
10178}
10179
10180sub get_sub_classes($$$)
10181{
10182 my ($ClassId, $LibVersion, $Recursive) = @_;
10183 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10184 my @Subs = ();
10185 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10186 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010187 if($Recursive)
10188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010189 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10190 push(@Subs, $SubSubId);
10191 }
10192 }
10193 push(@Subs, $SubId);
10194 }
10195 return @Subs;
10196}
10197
10198sub get_base_classes($$$)
10199{
10200 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010201 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010202 return () if(not defined $ClassType{"Base"});
10203 my @Bases = ();
10204 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10205 keys(%{$ClassType{"Base"}}))
10206 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010207 if($Recursive)
10208 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010209 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10210 push(@Bases, $SubBaseId);
10211 }
10212 }
10213 push(@Bases, $BaseId);
10214 }
10215 return @Bases;
10216}
10217
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010218sub getVTable_Model($$)
10219{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010220 my ($ClassId, $LibVersion) = @_;
10221 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10222 my @Elements = ();
10223 foreach my $BaseId (@Bases, $ClassId)
10224 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010225 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010226 {
10227 if(defined $VirtualTable{$LibVersion}{$BName})
10228 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010229 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10230 if($UsedDump{$LibVersion}{"DWARF"}) {
10231 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10232 }
10233 else {
10234 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10235 }
10236 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010237 push(@Elements, $VFunc);
10238 }
10239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010240 }
10241 }
10242 return @Elements;
10243}
10244
10245sub getVShift($$)
10246{
10247 my ($ClassId, $LibVersion) = @_;
10248 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10249 my $VShift = 0;
10250 foreach my $BaseId (@Bases)
10251 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010252 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010253 {
10254 if(defined $VirtualTable{$LibVersion}{$BName}) {
10255 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010257 }
10258 }
10259 return $VShift;
10260}
10261
10262sub getShift($$)
10263{
10264 my ($ClassId, $LibVersion) = @_;
10265 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10266 my $Shift = 0;
10267 foreach my $BaseId (@Bases)
10268 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010269 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010270 {
10271 if($Size!=1)
10272 { # not empty base class
10273 $Shift+=$Size;
10274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010275 }
10276 }
10277 return $Shift;
10278}
10279
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010280sub getVTable_Size($$)
10281{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010282 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010283 my $Size = 0;
10284 # three approaches
10285 if(not $Size)
10286 { # real size
10287 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10288 $Size = keys(%VTable);
10289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010290 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010291 if(not $Size)
10292 { # shared library symbol size
10293 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10294 $Size /= $WORD_SIZE{$LibVersion};
10295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010296 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010297 if(not $Size)
10298 { # model size
10299 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10300 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10301 }
10302 }
10303 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010304}
10305
10306sub isCopyingClass($$)
10307{
10308 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010309 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010310}
10311
10312sub isLeafClass($$)
10313{
10314 my ($ClassId, $LibVersion) = @_;
10315 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10316}
10317
10318sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010319{ # check structured type for public fields
10320 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010321}
10322
10323sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010324{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010325 my ($TypePtr, $Skip, $Start, $End) = @_;
10326 return 0 if(not $TypePtr);
10327 if($End==-1) {
10328 $End = keys(%{$TypePtr->{"Memb"}})-1;
10329 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010330 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010331 {
10332 if($Skip and $Skip->{$MemPos})
10333 { # skip removed/added fields
10334 next;
10335 }
10336 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10337 {
10338 if(isPublic($TypePtr, $MemPos)) {
10339 return ($MemPos+1);
10340 }
10341 }
10342 }
10343 return 0;
10344}
10345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010346sub isReserved($)
10347{ # reserved fields == private
10348 my $MName = $_[0];
10349 if($MName=~/reserved|padding|f_spare/i) {
10350 return 1;
10351 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010352 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010353 return 1;
10354 }
10355 if($MName=~/(pad\d+)/i) {
10356 return 1;
10357 }
10358 return 0;
10359}
10360
10361sub isPublic($$)
10362{
10363 my ($TypePtr, $FieldPos) = @_;
10364 return 0 if(not $TypePtr);
10365 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10366 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10367 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10368 { # by name in C language
10369 # FIXME: add other methods to detect private members
10370 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10371 if($MName=~/priv|abidata|parent_object/i)
10372 { # C-styled private data
10373 return 0;
10374 }
10375 if(lc($MName) eq "abi")
10376 { # ABI information/reserved field
10377 return 0;
10378 }
10379 if(isReserved($MName))
10380 { # reserved fields
10381 return 0;
10382 }
10383 return 1;
10384 }
10385 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10386 { # by access in C++ language
10387 return 1;
10388 }
10389 return 0;
10390}
10391
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010392sub getVTable_Real($$)
10393{
10394 my ($ClassName, $LibVersion) = @_;
10395 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10396 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010397 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010398 if(defined $Type{"VTable"}) {
10399 return %{$Type{"VTable"}};
10400 }
10401 }
10402 return ();
10403}
10404
10405sub cmpVTables($)
10406{
10407 my $ClassName = $_[0];
10408 my $Res = cmpVTables_Real($ClassName, 1);
10409 if($Res==-1) {
10410 $Res = cmpVTables_Model($ClassName);
10411 }
10412 return $Res;
10413}
10414
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010415sub cmpVTables_Model($)
10416{
10417 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010418 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010419 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010421 return 1;
10422 }
10423 }
10424 return 0;
10425}
10426
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010427sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010428{
10429 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010430 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10431 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010432 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 my %VTable_Old = getVTable_Real($ClassName, 1);
10434 my %VTable_New = getVTable_Real($ClassName, 2);
10435 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010436 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010437 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010438 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010439 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10441 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010442 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010444 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010445 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010446 my $Entry1 = $VTable_Old{$Offset};
10447 if(not defined $VTable_New{$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 or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010451 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 $Entry1 = simpleVEntry($Entry1);
10454 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010455
10456 if($Entry1=~/ 0x/ and $Entry2=~/ 0x/)
10457 { # NOTE: problem with vtable-dumper
10458 next;
10459 }
10460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010461 if($Entry1 ne $Entry2)
10462 { # register as changed
10463 if($Entry1=~/::([^:]+)\Z/)
10464 {
10465 my $M1 = $1;
10466 if($Entry2=~/::([^:]+)\Z/)
10467 {
10468 my $M2 = $1;
10469 if($M1 eq $M2)
10470 { # overridden
10471 next;
10472 }
10473 }
10474 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010475 if(differentDumps("G"))
10476 {
10477 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10478 {
10479 # GCC 4.6.1: -0x00000000000000010
10480 # GCC 4.7.0: -16
10481 next;
10482 }
10483 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010484 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010485 }
10486 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488}
10489
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010490sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010491{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010492 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10494 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010495 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496 { # already registered
10497 next;
10498 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010501 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010502 foreach my $Symbol (@Affected)
10503 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010504 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010506 "Target"=>$ClassName);
10507 }
10508 }
10509 }
10510}
10511
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010512sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010514 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010515 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010516 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010517 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010519 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010521 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010522 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 if($TName_Tid{1}{$ClassName}
10524 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010525 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 if(defined $CompleteSignature{1}{$Symbol}
10527 and $CompleteSignature{1}{$Symbol}{"Virt"})
10528 { # override some method in v.1
10529 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010530 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010531 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010532 }
10533 }
10534 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010535 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010537 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010538 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010539 if($TName_Tid{2}{$ClassName}
10540 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010541 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010542 if(defined $CompleteSignature{2}{$Symbol}
10543 and $CompleteSignature{2}{$Symbol}{"Virt"})
10544 { # override some method in v.2
10545 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010546 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010547 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010548 }
10549 }
10550 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010551 if($Level eq "Binary")
10552 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010553 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010554 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10555 { # check replacements, including pure virtual methods
10556 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10557 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010558 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010559 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10560 if($AddedPos==$RemovedPos)
10561 {
10562 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10563 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10564 last; # other methods will be reported as "added" or "removed"
10565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010567 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10568 {
10569 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10570 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010571 next;
10572 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010573 my $ProblemType = "Virtual_Replacement";
10574 my @Affected = ($RemovedVFunc);
10575 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10576 { # pure methods
10577 if(not isUsedClass($ClassId, 1, $Level))
10578 { # not a parameter of some exported method
10579 next;
10580 }
10581 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010582
10583 # affected all methods (both virtual and non-virtual ones)
10584 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10585 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010587 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010588 foreach my $AffectedInt (@Affected)
10589 {
10590 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10591 { # affected exported methods only
10592 next;
10593 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010594 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10595 next;
10596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010597 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10598 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010599 "Target"=>get_Signature($AddedVFunc, 2),
10600 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010602 }
10603 }
10604 }
10605 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010606 if(not checkDump(1, "2.0")
10607 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010608 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010609 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010610 return;
10611 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010612 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010613 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010614 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 next if(not $ClassId_Old);
10616 if(not isCreatable($ClassId_Old, 1))
10617 { # skip classes without public constructors (including auto-generated)
10618 # example: class has only a private exported or private inline constructor
10619 next;
10620 }
10621 if($ClassName=~/>/)
10622 { # skip affected template instances
10623 next;
10624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010625 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010626 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010627 if(not $ClassId_New) {
10628 next;
10629 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010630 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010631 if($Class_New{"Type"}!~/Class|Struct/)
10632 { # became typedef
10633 if($Level eq "Binary") {
10634 next;
10635 }
10636 if($Level eq "Source")
10637 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010638 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010639 if($Class_New{"Type"}!~/Class|Struct/) {
10640 next;
10641 }
10642 $ClassId_New = $Class_New{"Tid"};
10643 }
10644 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010645
10646 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10647 { # incomplete info in the ABI dump
10648 next;
10649 }
10650
10651
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010652 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10653 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 +040010654
10655 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10656 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10657
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010658 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010659 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10660 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010661 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10662 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 my $Shift_Old = getShift($ClassId_Old, 1);
10664 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010665 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010666 my ($Added, $Removed) = (0, 0);
10667 my @StableBases_Old = ();
10668 foreach my $BaseId (@Bases_Old)
10669 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010670 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010671 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010672 push(@StableBases_Old, $BaseId);
10673 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010674 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010675 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 { # removed base
10677 # excluding namespace::SomeClass to SomeClass renaming
10678 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010679 if($Level eq "Binary")
10680 { # Binary-level
10681 if($Shift_Old ne $Shift_New)
10682 { # affected fields
10683 if(havePubFields(\%Class_Old)) {
10684 $ProblemKind .= "_And_Shift";
10685 }
10686 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10687 $ProblemKind .= "_And_Size";
10688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010689 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010690 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10691 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010692 { # affected v-table
10693 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010694 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 }
10696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010697 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010698 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10699 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010700 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10701 {
10702 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10703 if($ProblemKind=~/VTable/) {
10704 $VTableChanged_M{$SubName}=1;
10705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010706 }
10707 }
10708 foreach my $Interface (@Affected)
10709 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010710 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10711 next;
10712 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010713 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010714 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010715 "Target"=>$BaseName,
10716 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10717 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10718 "Shift"=>abs($Shift_New-$Shift_Old) );
10719 }
10720 $Removed+=1;
10721 }
10722 }
10723 my @StableBases_New = ();
10724 foreach my $BaseId (@Bases_New)
10725 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010726 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010727 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010728 push(@StableBases_New, $BaseId);
10729 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010730 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010731 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010732 { # added base
10733 # excluding namespace::SomeClass to SomeClass renaming
10734 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010735 if($Level eq "Binary")
10736 { # Binary-level
10737 if($Shift_Old ne $Shift_New)
10738 { # affected fields
10739 if(havePubFields(\%Class_Old)) {
10740 $ProblemKind .= "_And_Shift";
10741 }
10742 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10743 $ProblemKind .= "_And_Size";
10744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010745 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010746 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10747 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010748 { # affected v-table
10749 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010750 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 }
10752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010753 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10755 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010756 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10757 {
10758 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10759 if($ProblemKind=~/VTable/) {
10760 $VTableChanged_M{$SubName}=1;
10761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010762 }
10763 }
10764 foreach my $Interface (@Affected)
10765 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010766 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10767 next;
10768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010769 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010770 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010771 "Target"=>$BaseName,
10772 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10773 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10774 "Shift"=>abs($Shift_New-$Shift_Old) );
10775 }
10776 $Added+=1;
10777 }
10778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010779 if($Level eq "Binary")
10780 { # Binary-level
10781 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010782 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10783 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010784 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010786 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010787 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010788 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010789 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10790 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010791 if($NewPos!=$OldPos)
10792 { # changed position of the base class
10793 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010794 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010795 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10796 next;
10797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010798 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10799 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010800 "Target"=>$BaseName,
10801 "Old_Value"=>$OldPos-1,
10802 "New_Value"=>$NewPos-1 );
10803 }
10804 }
10805 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10806 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10807 { # became non-virtual base
10808 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10809 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010810 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10811 next;
10812 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010813 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10814 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010815 "Target"=>$BaseName );
10816 }
10817 }
10818 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10819 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10820 { # became virtual base
10821 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10822 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010823 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10824 next;
10825 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010826 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10827 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010828 "Target"=>$BaseName );
10829 }
10830 }
10831 }
10832 }
10833 # detect size changes in base classes
10834 if($Shift_Old!=$Shift_New)
10835 { # size of allocable class
10836 foreach my $BaseId (@StableBases_Old)
10837 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010838 my %BaseType = get_Type($BaseId, 1);
10839 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010840 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 if($Size_Old ne $Size_New
10842 and $Size_Old and $Size_New)
10843 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010844 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010845 if(isCopyingClass($BaseId, 1)) {
10846 $ProblemType = "Size_Of_Copying_Class";
10847 }
10848 elsif($AllocableClass{1}{$BaseType{"Name"}})
10849 {
10850 if($Size_New>$Size_Old)
10851 { # increased size
10852 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010853 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010854 else
10855 { # decreased size
10856 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10857 if(not havePubFields(\%Class_Old))
10858 { # affected class has no public members
10859 next;
10860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010862 }
10863 next if(not $ProblemType);
10864 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10865 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010866 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10867 next;
10868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010869 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10870 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010871 "Target"=>$BaseType{"Name"},
10872 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10873 "New_Size"=>$Size_New*$BYTE_SIZE );
10874 }
10875 }
10876 }
10877 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010878 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010879 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010880 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 { # compare virtual tables size in base classes
10882 my $VShift_Old = getVShift($ClassId_Old, 1);
10883 my $VShift_New = getVShift($ClassId_New, 2);
10884 if($VShift_Old ne $VShift_New)
10885 { # changes in the base class or changes in the list of base classes
10886 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10887 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10888 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010889 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010890 foreach my $BaseId (@AllBases_Old)
10891 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010892 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010893 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010894 { # lost base
10895 next;
10896 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010897 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10898 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010899 if($VSize_Old!=$VSize_New)
10900 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010901 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010902 { # TODO: affected non-virtual methods?
10903 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010904 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10905 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010906 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010907 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010908 { # skip interfaces that have not changed the absolute virtual position
10909 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010910 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010911 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10912 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010913 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010914 $VTableChanged_M{$BaseType{"Name"}} = 1;
10915 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010916 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10917 { # the reason of the layout change: added virtual functions
10918 next if($VirtualReplacement{$VirtFunc});
10919 my $ProblemType = "Added_Virtual_Method";
10920 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10921 $ProblemType = "Added_Pure_Virtual_Method";
10922 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010923 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010925 "Target"=>get_Signature($VirtFunc, 2) );
10926 }
10927 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10928 { # the reason of the layout change: removed virtual functions
10929 next if($VirtualReplacement{$VirtFunc});
10930 my $ProblemType = "Removed_Virtual_Method";
10931 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10932 $ProblemType = "Removed_Pure_Virtual_Method";
10933 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010934 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010935 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010936 "Target"=>get_Signature($VirtFunc, 1) );
10937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010938 }
10939 }
10940 }
10941 }
10942 }
10943 }
10944 }
10945}
10946
10947sub isCreatable($$)
10948{
10949 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010950 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010951 or isCopyingClass($ClassId, $LibVersion)) {
10952 return 1;
10953 }
10954 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10955 { # Fix for incomplete data: if this class has
10956 # a base class then it should also has a constructor
10957 return 1;
10958 }
10959 if($ReturnedClass{$LibVersion}{$ClassId})
10960 { # returned by some method of this class
10961 # or any other class
10962 return 1;
10963 }
10964 return 0;
10965}
10966
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010967sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010968{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010969 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010970 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10971 { # parameter of some exported method
10972 return 1;
10973 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010974 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10975 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010976 { # method from target class
10977 return 1;
10978 }
10979 return 0;
10980}
10981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010982sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010983{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010984 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010985 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010986 # - virtual
10987 # - pure-virtual
10988 # - non-virtual
10989 if($CompleteSignature{1}{$Interface}{"Data"})
10990 { # global data is not affected
10991 return;
10992 }
10993 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010994 if(not $Class_Id) {
10995 return;
10996 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010997 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010998 if(cmpVTables_Real($CName, 1)==0)
10999 { # no changes
11000 return;
11001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 $CheckedTypes{$Level}{$CName} = 1;
11003 if($Level eq "Binary")
11004 { # Binary-level
11005 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11006 and not isUsedClass($Class_Id, 1, $Level))
11007 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011008 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011009 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011010 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011011 }
11012 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11013 {
11014 if(defined $VirtualTable{2}{$CName}{$Func}
11015 and defined $CompleteSignature{2}{$Func})
11016 {
11017 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11018 and $CompleteSignature{2}{$Func}{"PureVirt"})
11019 { # became pure virtual
11020 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11021 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011022 "Target"=>get_Signature_M($Func, 1) );
11023 $VTableChanged_M{$CName} = 1;
11024 }
11025 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11026 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11027 { # became non-pure virtual
11028 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11029 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011030 "Target"=>get_Signature_M($Func, 1) );
11031 $VTableChanged_M{$CName} = 1;
11032 }
11033 }
11034 }
11035 if($Level eq "Binary")
11036 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011037 # check virtual table structure
11038 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11039 {
11040 next if($Interface eq $AddedVFunc);
11041 next if($VirtualReplacement{$AddedVFunc});
11042 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11043 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11044 { # pure virtual methods affect all others (virtual and non-virtual)
11045 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011046 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011047 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011048 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011049 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011050 elsif(not defined $VirtualTable{1}{$CName}
11051 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011053 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054 { # became polymorphous class, added v-table pointer
11055 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011056 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011057 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 }
11060 else
11061 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011062 my $VSize_Old = getVTable_Size($CName, 1);
11063 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011064 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 if(isCopyingClass($Class_Id, 1))
11066 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11067 my $ProblemType = "Added_Virtual_Method";
11068 if(isLeafClass($Class_Id, 1)) {
11069 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11070 }
11071 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11072 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011073 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011074 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011076 else
11077 {
11078 my $ProblemType = "Added_Virtual_Method";
11079 if(isLeafClass($Class_Id, 1)) {
11080 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11081 }
11082 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11083 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011084 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011085 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011087 }
11088 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11090 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011091 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011092 if(defined $VirtualTable{1}{$CName}
11093 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011094 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011095 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11096 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011097
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011098 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011100 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11101 foreach my $ASymbol (@Affected)
11102 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011103 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11104 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011105 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011106 next;
11107 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011108 }
11109 $CheckedSymbols{$Level}{$ASymbol} = 1;
11110 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11111 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011112 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011113 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011116 }
11117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011118 else {
11119 # safe
11120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011122 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11123 {
11124 next if($VirtualReplacement{$RemovedVFunc});
11125 if($RemovedVFunc eq $Interface
11126 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11127 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011128 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 next;
11130 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011131 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011132 { # became non-polymorphous class, removed v-table pointer
11133 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11134 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011136 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 }
11138 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11139 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11140 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011141 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011142 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011143 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11144 next;
11145 }
11146 my $VPos_New = -1;
11147 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011149 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11150 }
11151 else
11152 {
11153 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011154 next;
11155 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011156 }
11157 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11158 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11159 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11160 {
11161 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11162 foreach my $ASymbol (@Affected)
11163 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011164 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11165 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011166 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011167 next;
11168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011169 }
11170 my $ProblemType = "Removed_Virtual_Method";
11171 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11172 $ProblemType = "Removed_Pure_Virtual_Method";
11173 }
11174 $CheckedSymbols{$Level}{$ASymbol} = 1;
11175 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11176 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011177 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011178 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011180 }
11181 }
11182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011183 }
11184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011185 else
11186 { # Source-level
11187 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011188 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011189 next if($Interface eq $AddedVFunc);
11190 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011191 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011192 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11193 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 "Target"=>get_Signature($AddedVFunc, 2) );
11195 }
11196 }
11197 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11198 {
11199 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11200 {
11201 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11202 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011203 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011204 }
11205 }
11206 }
11207}
11208
11209sub find_MemberPair_Pos_byName($$)
11210{
11211 my ($Member_Name, $Pair_Type) = @_;
11212 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11213 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11214 {
11215 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11216 {
11217 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11218 $Name=~s/\A[_]+|[_]+\Z//g;
11219 if($Name eq $Member_Name) {
11220 return $MemberPair_Pos;
11221 }
11222 }
11223 }
11224 return "lost";
11225}
11226
11227sub find_MemberPair_Pos_byVal($$)
11228{
11229 my ($Member_Value, $Pair_Type) = @_;
11230 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11231 {
11232 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11233 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11234 return $MemberPair_Pos;
11235 }
11236 }
11237 return "lost";
11238}
11239
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011240sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011241{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011242 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011243 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011244 if( $_->{"T1"} eq $_[0]
11245 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011246 {
11247 return 1;
11248 }
11249 }
11250 return 0;
11251}
11252
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011253sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011254{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011255 my %IDs = (
11256 "T1" => $_[0],
11257 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011258 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011259 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011260}
11261
11262sub isRenamed($$$$$)
11263{
11264 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11265 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11266 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011267 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011268 if(not defined $Type2->{"Memb"}{$MemPos}) {
11269 return "";
11270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011271 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011272 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011273
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11275 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 if($MemberPair_Pos_Rev eq "lost")
11277 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011278 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11279 { # base type match
11280 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011282 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11283 { # exact type match
11284 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011285 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011286 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11287 { # size match
11288 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011289 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011290 if(isReserved($Pair_Name))
11291 { # reserved fields
11292 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011293 }
11294 }
11295 return "";
11296}
11297
11298sub isLastElem($$)
11299{
11300 my ($Pos, $TypeRef) = @_;
11301 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11302 if($Name=~/last|count|max|total/i)
11303 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11304 return 1;
11305 }
11306 elsif($Name=~/END|NLIMITS\Z/)
11307 { # __RLIMIT_NLIMITS
11308 return 1;
11309 }
11310 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11311 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11312 { # NImageFormats, NColorRoles
11313 return 1;
11314 }
11315 return 0;
11316}
11317
11318sub nonComparable($$)
11319{
11320 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011321
11322 my $N1 = $T1->{"Name"};
11323 my $N2 = $T2->{"Name"};
11324
11325 $N1=~s/\A(struct|union|enum) //;
11326 $N2=~s/\A(struct|union|enum) //;
11327
11328 if($N1 ne $N2
11329 and not isAnon($N1)
11330 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011331 { # different names
11332 if($T1->{"Type"} ne "Pointer"
11333 or $T2->{"Type"} ne "Pointer")
11334 { # compare base types
11335 return 1;
11336 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011337 if($N1!~/\Avoid\s*\*/
11338 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011339 {
11340 return 1;
11341 }
11342 }
11343 elsif($T1->{"Type"} ne $T2->{"Type"})
11344 { # different types
11345 if($T1->{"Type"} eq "Class"
11346 and $T2->{"Type"} eq "Struct")
11347 { # "class" to "struct"
11348 return 0;
11349 }
11350 elsif($T2->{"Type"} eq "Class"
11351 and $T1->{"Type"} eq "Struct")
11352 { # "struct" to "class"
11353 return 0;
11354 }
11355 else
11356 { # "class" to "enum"
11357 # "union" to "class"
11358 # ...
11359 return 1;
11360 }
11361 }
11362 return 0;
11363}
11364
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011365sub isOpaque($)
11366{
11367 my $T = $_[0];
11368 if(not defined $T->{"Memb"})
11369 {
11370 return 1;
11371 }
11372 return 0;
11373}
11374
11375sub removeVPtr($)
11376{ # support for old ABI dumps
11377 my $TPtr = $_[0];
11378 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11379 if($#Pos>=1)
11380 {
11381 foreach my $Pos (0 .. $#Pos-1)
11382 {
11383 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11384 }
11385 delete($TPtr->{"Memb"}{$#Pos});
11386 }
11387}
11388
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011389sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011390{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011391 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011392 return {} if(not $Type1_Id or not $Type2_Id);
11393
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011394 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011395 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011396 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011397 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011398
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011399 my %Type1 = get_Type($Type1_Id, 1);
11400 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011401 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011402 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011403 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011404
11405 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011406 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11407 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011408
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011409 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11410
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011411 my %SubProblems = ();
11412
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011413 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11414 {
11415 if($Type1_Pure{"Type"}=~/Struct|Union/
11416 and $Type2_Pure{"Type"}=~/Struct|Union/)
11417 {
11418 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11419 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011420 if(not defined $UsedDump{1}{"DWARF"}
11421 and not defined $UsedDump{2}{"DWARF"})
11422 {
11423 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11424 "Target"=>$Type1_Pure{"Name"},
11425 "Type_Name"=>$Type1_Pure{"Name"} );
11426 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011427
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011428 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011429 }
11430 }
11431 }
11432
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011433 if(not $Type1_Pure{"Size"}
11434 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011435 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011436 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11437 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11438 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011439 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011440 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011441 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011442 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011443 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011444 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011445 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011446 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11447 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11448 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011449
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011450 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11451 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011452 }
11453
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011454 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11455 { # support for old ABI dumps
11456 # _vptr field added in 3.0
11457 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11458 {
11459 if(defined $Type2_Pure{"Memb"}
11460 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11461 {
11462 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11463 delete($Type2_Pure{"Memb"}{0});
11464 }
11465 else {
11466 removeVPtr(\%Type2_Pure);
11467 }
11468 }
11469 }
11470 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11471 {
11472 if(defined $Type1_Pure{"Memb"}
11473 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11474 {
11475 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11476 delete($Type1_Pure{"Memb"}{0});
11477 }
11478 else {
11479 removeVPtr(\%Type1_Pure);
11480 }
11481 }
11482 }
11483 }
11484
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011485 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11486 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011487
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011488 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011489 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11490 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011491 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011492 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11493 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011494 if($Base_1{"Name"} ne $Base_2{"Name"})
11495 {
11496 if(differentDumps("G")
11497 or differentDumps("V"))
11498 { # different GCC versions or different dumps
11499 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11500 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11501 # std::__va_list and __va_list
11502 $Base_1{"Name"}=~s/\A(\w+::)+//;
11503 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011504 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11505 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011507 }
11508 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11509 and $Base_1{"Name"} ne $Base_2{"Name"})
11510 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011511 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011512 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011513 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011514 {
11515 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11516 "Target"=>$Typedef_1{"Name"},
11517 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011518 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11519 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11520 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011521 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11522 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011523 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011524 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011525 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11526 {
11527 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11528 "Target"=>$Typedef_1{"Name"},
11529 "Type_Name"=>$Typedef_1{"Name"},
11530 "Old_Value"=>$Base_1{"Name"},
11531 "New_Value"=>$Base_2{"Name"} );
11532 }
11533 else
11534 {
11535 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11536 "Target"=>$Typedef_1{"Name"},
11537 "Type_Name"=>$Typedef_1{"Name"},
11538 "Old_Value"=>$Base_1{"Name"},
11539 "New_Value"=>$Base_2{"Name"} );
11540 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011542 }
11543 }
11544 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11545 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011546 my $TT1 = $Type1_Pure{"Type"};
11547 my $TT2 = $Type2_Pure{"Type"};
11548
11549 if($TT1 ne $TT2
11550 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011551 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011552 my $Short1 = $Type1_Pure{"Name"};
11553 my $Short2 = $Type2_Pure{"Name"};
11554
11555 $Short1=~s/\A\Q$TT1\E //ig;
11556 $Short2=~s/\A\Q$TT2\E //ig;
11557
11558 if($Short1 eq $Short2)
11559 {
11560 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11561 "Target"=>$Type1_Pure{"Name"},
11562 "Type_Name"=>$Type1_Pure{"Name"},
11563 "Old_Value"=>lc($Type1_Pure{"Type"}),
11564 "New_Value"=>lc($Type2_Pure{"Type"}) );
11565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011566 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011567 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011568 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011569 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011570 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11571 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11572 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11573 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011574 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011575 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011576 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011577 {
11578 my $ProblemKind = "DataType_Size";
11579 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011580 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011581 {
11582 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11583 $ProblemKind = "Size_Of_Copying_Class";
11584 }
11585 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11586 {
11587 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11588 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11589 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011590 else
11591 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011592 # descreased size of allocable class
11593 # it has no special effects
11594 }
11595 }
11596 }
11597 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11598 "Target"=>$Type1_Pure{"Name"},
11599 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011601 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 }
11603 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011604 if(defined $Type1_Pure{"BaseType"}
11605 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011606 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011607 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11608 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011609 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011610 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11611 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011612 }
11613 }
11614 }
11615 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11616 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11617 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11618 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11619 { # detect removed and renamed fields
11620 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11621 next if(not $Member_Name);
11622 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);
11623 if($MemberPair_Pos eq "lost")
11624 {
11625 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11626 {
11627 if(isUnnamed($Member_Name))
11628 { # support for old-version dumps
11629 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011630 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011631 next;
11632 }
11633 }
11634 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11635 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011636 $RenamedField{$Member_Pos} = $RenamedTo;
11637 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011638 }
11639 else
11640 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011641 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011642 }
11643 }
11644 elsif($Type1_Pure{"Type"} eq "Enum")
11645 {
11646 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11647 next if($Member_Value1 eq "");
11648 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11649 if($MemberPair_Pos ne "lost")
11650 { # renamed
11651 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11652 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11653 if($MemberPair_Pos_Rev eq "lost")
11654 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011655 $RenamedField{$Member_Pos} = $RenamedTo;
11656 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011657 }
11658 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011659 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011660 }
11661 }
11662 else
11663 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011664 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 }
11666 }
11667 }
11668 else
11669 { # related
11670 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11671 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11672 }
11673 }
11674 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11675 { # detect added fields
11676 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11677 next if(not $Member_Name);
11678 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);
11679 if($MemberPair_Pos eq "lost")
11680 {
11681 if(isUnnamed($Member_Name))
11682 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011683 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011684 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011685 next;
11686 }
11687 }
11688 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11689 {
11690 if(not $RenamedField_Rev{$Member_Pos})
11691 { # added
11692 $AddedField{$Member_Pos}=1;
11693 }
11694 }
11695 }
11696 }
11697 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11698 { # detect moved fields
11699 my (%RelPos, %RelPosName, %AbsPos) = ();
11700 my $Pos = 0;
11701 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11702 { # relative positions in 1st version
11703 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11704 next if(not $Member_Name);
11705 if(not $RemovedField{$Member_Pos})
11706 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011707 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011708 $RelPosName{1}{$Pos} = $Member_Name;
11709 $AbsPos{1}{$Pos++} = $Member_Pos;
11710 }
11711 }
11712 $Pos = 0;
11713 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11714 { # relative positions in 2nd version
11715 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11716 next if(not $Member_Name);
11717 if(not $AddedField{$Member_Pos})
11718 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011719 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011720 $RelPosName{2}{$Pos} = $Member_Name;
11721 $AbsPos{2}{$Pos++} = $Member_Pos;
11722 }
11723 }
11724 foreach my $Member_Name (keys(%{$RelPos{1}}))
11725 {
11726 my $RPos1 = $RelPos{1}{$Member_Name};
11727 my $AbsPos1 = $NameToPosA{$Member_Name};
11728 my $Member_Name2 = $Member_Name;
11729 if(my $RenamedTo = $RenamedField{$AbsPos1})
11730 { # renamed
11731 $Member_Name2 = $RenamedTo;
11732 }
11733 my $RPos2 = $RelPos{2}{$Member_Name2};
11734 if($RPos2 ne "" and $RPos1 ne $RPos2)
11735 { # different relative positions
11736 my $AbsPos2 = $NameToPosB{$Member_Name2};
11737 if($AbsPos1 ne $AbsPos2)
11738 { # different absolute positions
11739 my $ProblemType = "Moved_Field";
11740 if(not isPublic(\%Type1_Pure, $AbsPos1))
11741 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011742 if($Level eq "Source") {
11743 next;
11744 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011745 $ProblemType = "Moved_Private_Field";
11746 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011747 if($Level eq "Binary"
11748 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011749 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011750 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011752 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011753 if($MemSize1 ne $MemSize2) {
11754 $ProblemType .= "_And_Size";
11755 }
11756 }
11757 if($ProblemType eq "Moved_Private_Field") {
11758 next;
11759 }
11760 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11761 "Target"=>$Member_Name,
11762 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011763 "Old_Value"=>$RPos1,
11764 "New_Value"=>$RPos2 );
11765 }
11766 }
11767 }
11768 }
11769 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011770 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011771 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11772 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011773 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 if(my $RenamedTo = $RenamedField{$Member_Pos})
11775 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011776 if(defined $Constants{2}{$Member_Name})
11777 {
11778 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11779 { # define OLD NEW
11780 next; # Safe
11781 }
11782 }
11783
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11785 {
11786 if(isPublic(\%Type1_Pure, $Member_Pos))
11787 {
11788 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11789 "Target"=>$Member_Name,
11790 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011791 "Old_Value"=>$Member_Name,
11792 "New_Value"=>$RenamedTo );
11793 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011794 elsif(isReserved($Member_Name))
11795 {
11796 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11797 "Target"=>$Member_Name,
11798 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011799 "Old_Value"=>$Member_Name,
11800 "New_Value"=>$RenamedTo );
11801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 }
11803 elsif($Type1_Pure{"Type"} eq "Enum")
11804 {
11805 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11806 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11807 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011808 "Old_Value"=>$Member_Name,
11809 "New_Value"=>$RenamedTo );
11810 }
11811 }
11812 elsif($RemovedField{$Member_Pos})
11813 { # removed
11814 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11815 {
11816 my $ProblemType = "Removed_Field";
11817 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011818 or isUnnamed($Member_Name))
11819 {
11820 if($Level eq "Source") {
11821 next;
11822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011823 $ProblemType = "Removed_Private_Field";
11824 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011825 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011826 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011827 {
11828 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11829 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011830 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 +040011831 { # changed offset
11832 $ProblemType .= "_And_Layout";
11833 }
11834 }
11835 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11836 { # affected size
11837 $ProblemType .= "_And_Size";
11838 }
11839 }
11840 if($ProblemType eq "Removed_Private_Field") {
11841 next;
11842 }
11843 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11844 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011845 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011846 }
11847 elsif($Type2_Pure{"Type"} eq "Union")
11848 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011849 if($Level eq "Binary"
11850 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011851 {
11852 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11853 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011854 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011855 }
11856 else
11857 {
11858 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11859 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011860 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011861 }
11862 }
11863 elsif($Type1_Pure{"Type"} eq "Enum")
11864 {
11865 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11866 "Target"=>$Member_Name,
11867 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011868 "Old_Value"=>$Member_Name );
11869 }
11870 }
11871 else
11872 { # changed
11873 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11874 if($Type1_Pure{"Type"} eq "Enum")
11875 {
11876 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11877 next if($Member_Value1 eq "");
11878 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11879 next if($Member_Value2 eq "");
11880 if($Member_Value1 ne $Member_Value2)
11881 {
11882 my $ProblemType = "Enum_Member_Value";
11883 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11884 $ProblemType = "Enum_Last_Member_Value";
11885 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011886 if($SkipConstants{1}{$Member_Name}) {
11887 $ProblemType = "Enum_Private_Member_Value";
11888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011889 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11890 "Target"=>$Member_Name,
11891 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011892 "Old_Value"=>$Member_Value1,
11893 "New_Value"=>$Member_Value2 );
11894 }
11895 }
11896 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11897 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011898 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11899 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11900
11901 if($Access1 ne "private"
11902 and $Access2 eq "private")
11903 {
11904 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11905 "Target"=>$Member_Name,
11906 "Type_Name"=>$Type1_Pure{"Name"});
11907 }
11908 elsif($Access1 ne "protected"
11909 and $Access1 ne "private"
11910 and $Access2 eq "protected")
11911 {
11912 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11913 "Target"=>$Member_Name,
11914 "Type_Name"=>$Type1_Pure{"Name"});
11915 }
11916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011917 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11918 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011919 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011920 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11921 $SizeV1 = $BSize1;
11922 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011923 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011924 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11925 $SizeV2 = $BSize2;
11926 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011927 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11928 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011929 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011930 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011931 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011932 {
11933 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11934 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11935 { # field size change (including anon-structures and unions)
11936 # - same types
11937 # - unnamed types
11938 # - bitfields
11939 my $ProblemType = "Field_Size";
11940 if(not isPublic(\%Type1_Pure, $Member_Pos)
11941 or isUnnamed($Member_Name))
11942 { # should not be accessed by applications, goes to "Low Severity"
11943 # example: "abidata" members in GStreamer types
11944 $ProblemType = "Private_".$ProblemType;
11945 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011946 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 +040011947 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011948 if($Type2_Pure{"Type"} ne "Union"
11949 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011951 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 +040011952 { # changed offset
11953 $ProblemType .= "_And_Layout";
11954 }
11955 }
11956 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11957 $ProblemType .= "_And_Type_Size";
11958 }
11959 }
11960 if($ProblemType eq "Private_Field_Size")
11961 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011962 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011963 if($ProblemType eq "Field_Size")
11964 {
11965 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11966 { # Low severity
11967 $ProblemType = "Struct_Field_Size_Increased";
11968 }
11969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 if($ProblemType)
11971 { # register a problem
11972 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11973 "Target"=>$Member_Name,
11974 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011975 "Old_Size"=>$SizeV1,
11976 "New_Size"=>$SizeV2);
11977 }
11978 }
11979 }
11980 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11981 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11982 { # do NOT check bitfield type changes
11983 next;
11984 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011985 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011986 {
11987 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11988 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11989 {
11990 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11991 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011992 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011993 }
11994 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11995 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11996 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011997 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011998 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011999 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012000 }
12001 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012002 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12003 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012005 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12006 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012007
12008 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012010 or $ProblemType eq "Field_Type_And_Size"
12011 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012012 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012013 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012014 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012015 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012016 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012017 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012018 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012019 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012020 }
12021 }
12022 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12023 {
12024 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012025 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012026 }
12027 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012028 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012029 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012030 }
12031 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12032 {
12033 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012034 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012035 }
12036 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012037 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012038 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012039 }
12040 }
12041 }
12042
12043 if($Level eq "Source")
12044 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012045 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012046 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012047 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12048 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012049
12050 if($ProblemType eq "Field_Type")
12051 {
12052 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012053 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012054 }
12055 }
12056 }
12057 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012058
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012059 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012060 {
12061 my $ProblemType_Init = $ProblemType;
12062 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012063 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012064 if(not isPublic(\%Type1_Pure, $Member_Pos)
12065 or isUnnamed($Member_Name)) {
12066 $ProblemType = "Private_".$ProblemType;
12067 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012068 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 +040012069 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012070 if($Type2_Pure{"Type"} ne "Union"
12071 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012072 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012073 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 +040012074 { # changed offset
12075 $ProblemType .= "_And_Layout";
12076 }
12077 }
12078 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12079 $ProblemType .= "_And_Type_Size";
12080 }
12081 }
12082 }
12083 else
12084 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012085 # TODO: Private_Field_Type rule?
12086
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 if(not isPublic(\%Type1_Pure, $Member_Pos)
12088 or isUnnamed($Member_Name)) {
12089 next;
12090 }
12091 }
12092 if($ProblemType eq "Private_Field_Type_And_Size")
12093 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 }
12095 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12096 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012097 "Type_Name"=>$Type1_Pure{"Name"});
12098
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012099 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012100 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012101 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012102 }
12103 }
12104 if(not isPublic(\%Type1_Pure, $Member_Pos))
12105 { # do NOT check internal type changes
12106 next;
12107 }
12108 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012109 { # checking member type changes
12110 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12111
12112 my %DupProblems = ();
12113
12114 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012115 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012116 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012117 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012118 if(not defined $AllAffected)
12119 {
12120 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12121 next;
12122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012123 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012124
12125 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12126 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12127
12128 if(not defined $AllAffected)
12129 {
12130 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012131 }
12132 }
12133 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012134
12135 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 }
12137 }
12138 }
12139 }
12140 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12141 { # checking added members, public and private
12142 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12143 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012144 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012145 if($AddedField{$Member_Pos})
12146 { # added
12147 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12148 {
12149 my $ProblemType = "Added_Field";
12150 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012151 or isUnnamed($Member_Name))
12152 {
12153 if($Level eq "Source") {
12154 next;
12155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012156 $ProblemType = "Added_Private_Field";
12157 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012158 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012159 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012160 {
12161 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12162 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012163 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 +040012164 { # changed offset
12165 $ProblemType .= "_And_Layout";
12166 }
12167 }
12168 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12169 $ProblemType .= "_And_Size";
12170 }
12171 }
12172 if($ProblemType eq "Added_Private_Field")
12173 { # skip added private fields
12174 next;
12175 }
12176 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12177 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012178 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012179 }
12180 elsif($Type2_Pure{"Type"} eq "Union")
12181 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012182 if($Level eq "Binary"
12183 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 {
12185 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12186 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012187 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012188 }
12189 else
12190 {
12191 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12192 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012193 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012194 }
12195 }
12196 elsif($Type2_Pure{"Type"} eq "Enum")
12197 {
12198 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12199 next if($Member_Value eq "");
12200 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12201 "Target"=>$Member_Name,
12202 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012203 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012204 }
12205 }
12206 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012207
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012208 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012209 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012210}
12211
12212sub isUnnamed($) {
12213 return $_[0]=~/\Aunnamed\d+\Z/;
12214}
12215
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012216sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012217{
12218 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012219 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12220 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12221 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12222 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012223 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012224 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012225 }
12226 return $TypeName;
12227}
12228
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012229sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012231 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012232 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012233 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12234 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12237 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012238 return () if(not $Type{"Type"});
12239 if($Type{"Type"} ne $Type_Type)
12240 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012241 return () if(not $Type{"BaseType"});
12242 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012243 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012244 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012245 return %Type;
12246}
12247
12248my %TypeSpecAttributes = (
12249 "Const" => 1,
12250 "Volatile" => 1,
12251 "ConstVolatile" => 1,
12252 "Restrict" => 1,
12253 "Typedef" => 1
12254);
12255
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012256sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012257{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012258 my ($TypeId, $Info) = @_;
12259 if(not $TypeId or not $Info
12260 or not $Info->{$TypeId}) {
12261 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012263 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12264 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12265 }
12266 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012267 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012269 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012271 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012272 return %Type;
12273}
12274
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012275sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012277 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012278 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012279 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12280 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012282 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12283 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012284 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12285 my $PLevel = 0;
12286 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12287 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012288 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012289 return $PLevel if(not $Type{"BaseType"});
12290 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12291 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12292 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012293}
12294
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012295sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012297 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012299 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12300 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012301 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012302 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12303 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012304 return %Type if(not $Type{"BaseType"});
12305 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012306 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012307 return %Type;
12308}
12309
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012310sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012311{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012312 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012314 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12315 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012316 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 my $Qual = "";
12318 if($Type{"Type"} eq "Pointer") {
12319 $Qual .= "*";
12320 }
12321 elsif($Type{"Type"} eq "Ref") {
12322 $Qual .= "&";
12323 }
12324 elsif($Type{"Type"} eq "ConstVolatile") {
12325 $Qual .= "const volatile";
12326 }
12327 elsif($Type{"Type"} eq "Const"
12328 or $Type{"Type"} eq "Volatile"
12329 or $Type{"Type"} eq "Restrict") {
12330 $Qual .= lc($Type{"Type"});
12331 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012332 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 return $BQual.$Qual;
12334}
12335
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012336sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012338 my ($TypeId, $Info) = @_;
12339 if(not $TypeId or not $Info
12340 or not $Info->{$TypeId}) {
12341 return ();
12342 }
12343 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012344 return %Type if(not $Type{"BaseType"});
12345 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012346 {
12347 if($Info->{$BTid}) {
12348 return %{$Info->{$BTid}};
12349 }
12350 else { # something is going wrong
12351 return ();
12352 }
12353 }
12354 else {
12355 return %Type;
12356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012357}
12358
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012359sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012360{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012361 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012362 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012363 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12364 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365}
12366
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012367sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012368{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012369 my $Symbol = $_[0];
12370 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12371}
12372
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012373sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012374 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12375}
12376
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012377sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012378{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012379 my ($SInfo, $LibVersion) = @_;
12380
12381 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012383 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012385 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 return 1;
12387 }
12388 }
12389 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012390 if(my $ShortName = $SInfo->{"ShortName"})
12391 {
12392 if(index($ShortName,"<")!=-1
12393 and index($ShortName,">")!=-1) {
12394 return 1;
12395 }
12396 }
12397
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012398 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399}
12400
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012401sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012402{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012403 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012404 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012405 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012406 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012407 { # class specialization
12408 return 1;
12409 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012410 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012411 { # method specialization
12412 return 1;
12413 }
12414 }
12415 return 0;
12416}
12417
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012418sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012419{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012420 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012421
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012422 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 { # non-public global data
12424 return 0;
12425 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012426
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012427 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012428 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012429 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012430 }
12431
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012432 if($Symbol=~/\A_Z/)
12433 {
12434 if($Symbol=~/[CD][3-4]E/) {
12435 return 0;
12436 }
12437 }
12438
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012439 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440 { # support for old ABI dumps in --headers-only mode
12441 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12442 {
12443 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12444 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012445 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 if(not $PType or $PType eq "Unknown") {
12447 return 0;
12448 }
12449 }
12450 }
12451 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012452 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012454 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12455
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 if($SkipSymbols{$LibVersion}{$Symbol})
12457 { # user defined symbols to ignore
12458 return 0;
12459 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012460
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012461 if($SymbolsListPath and not $SymbolsList{$Symbol})
12462 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012463 if(not $TargetHeadersPath or not $Header
12464 or not is_target_header($Header, 1))
12465 { # -symbols-list | -headers-list
12466 return 0;
12467 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012468 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012469
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012470 if($AppPath and not $SymbolsList_App{$Symbol})
12471 { # user defined symbols (in application)
12472 return 0;
12473 }
12474
12475 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12476
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012477 if($ClassId)
12478 {
12479 if(not isTargetType($ClassId, $LibVersion)) {
12480 return 0;
12481 }
12482 }
12483
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012484 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12485 if(not $NameSpace and $ClassId)
12486 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012487 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012488 }
12489 if($NameSpace)
12490 { # user defined namespaces to ignore
12491 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12492 return 0;
12493 }
12494 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12495 { # nested namespaces
12496 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12497 return 0;
12498 }
12499 }
12500 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012501 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012502 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012503 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012504 { # --skip-headers or <skip_headers> (not <skip_including>)
12505 if($Skip==1) {
12506 return 0;
12507 }
12508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012510 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012511 { # user defined types
12512 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12513
12514 if(not $TypesList{$CName})
12515 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012516 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12517 {
12518 $CName=~s/\A\Q$NS\E\:\://g;
12519 }
12520
12521 if(not $TypesList{$CName})
12522 {
12523 my $Found = 0;
12524
12525 while($CName=~s/\:\:.+?\Z//)
12526 {
12527 if($TypesList{$CName})
12528 {
12529 $Found = 1;
12530 last;
12531 }
12532 }
12533
12534 if(not $Found) {
12535 return 0;
12536 }
12537 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012538 }
12539 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012540
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012541 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12542 { # non-target symbols
12543 return 0;
12544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012545 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012546 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012547 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12548 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012549 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012550 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12551 { # inline virtual methods
12552 if($Type=~/InlineVirt/) {
12553 return 1;
12554 }
12555 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12556 if(not $Allocable)
12557 { # check bases
12558 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12559 {
12560 if(not isCopyingClass($DCId, $LibVersion))
12561 { # exists a derived class without default c-tor
12562 $Allocable=1;
12563 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012565 }
12566 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012567 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012568 return 0;
12569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012571 else
12572 { # inline non-virtual methods
12573 return 0;
12574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 }
12577 }
12578 return 1;
12579}
12580
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012581sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012582{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012583 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012584 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12585 {
12586 if(link_symbol($Symbol, 1, "+Deps"))
12587 { # linker can find a new symbol
12588 # in the old-version library
12589 # So, it's not a new symbol
12590 next;
12591 }
12592 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012593 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012594 next;
12595 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012596 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597 }
12598}
12599
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012600sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012601{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012602 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012603 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12604 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 if(link_symbol($Symbol, 2, "+Deps"))
12606 { # linker can find an old symbol
12607 # in the new-version library
12608 next;
12609 }
12610 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012611 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612 next;
12613 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012614 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 }
12616}
12617
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012618sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012619{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012620 my $Level = $_[0];
12621 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012622 { # checking added symbols
12623 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012624 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012625 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012626 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012627 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012628 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012629 { # checking removed symbols
12630 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012631 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012632 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012633 { # skip v-tables for templates, that should not be imported by applications
12634 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012635 if(my $CName = $VTableClass{$Symbol})
12636 {
12637 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12638 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012639 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012640 next;
12641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642 }
12643 }
12644 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012645 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012646 }
12647 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12648 { # symbols for pure virtual methods cannot be called by clients
12649 next;
12650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012651 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 }
12653}
12654
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012655sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012656{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012657 my ($LibVersion, $V) = @_;
12658 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12659 return $Cache{"checkDump"}{$LibVersion}{$V};
12660 }
12661 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012662}
12663
12664sub detectAdded_H($)
12665{
12666 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012667 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12668 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012669 if($Level eq "Source")
12670 { # remove symbol version
12671 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12672 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012673
12674 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12675 { # skip artificial constructors
12676 next;
12677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012678 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012679 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12680 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012681 next;
12682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012683 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012684 next;
12685 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012686 if(not defined $CompleteSignature{1}{$Symbol}
12687 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12688 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012689 if($UsedDump{2}{"SrcBin"})
12690 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012691 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012692 { # support for old and different (!) ABI dumps
12693 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12694 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012695 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012696 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012697 {
12698 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12699 {
12700 if($Lang eq "C")
12701 { # support for old ABI dumps: missed extern "C" functions
12702 next;
12703 }
12704 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012705 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012706 else
12707 {
12708 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012709 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012710 next;
12711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012712 }
12713 }
12714 }
12715 }
12716 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012717 }
12718 }
12719}
12720
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012721sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012722{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012723 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012724 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12725 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012726 if($Level eq "Source")
12727 { # remove symbol version
12728 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12729 $Symbol=$SN;
12730 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012731 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12732 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012733 next;
12734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012735 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012736 next;
12737 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012738 if(not defined $CompleteSignature{2}{$Symbol}
12739 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012740 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012741 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012742 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012743 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012744 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012745 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12746 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012747 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012748 if($CheckHeadersOnly)
12749 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012750 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12751 {
12752 if($Lang eq "C")
12753 { # support for old ABI dumps: missed extern "C" functions
12754 next;
12755 }
12756 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012757 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012758 else
12759 {
12760 if(not link_symbol($Symbol, 1, "-Deps"))
12761 { # skip removed inline symbols
12762 next;
12763 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012764 }
12765 }
12766 }
12767 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012768 if(not checkDump(1, "2.15"))
12769 {
12770 if($Symbol=~/_IT_E\Z/)
12771 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12772 next;
12773 }
12774 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012775 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12776 {
12777 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12778 {
12779 if(defined $Constants{2}{$Short})
12780 {
12781 my $Val = $Constants{2}{$Short}{"Value"};
12782 if(defined $Func_ShortName{2}{$Val})
12783 { # old name defined to new
12784 next;
12785 }
12786 }
12787 }
12788
12789 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012790 $RemovedInt{$Level}{$Symbol} = 1;
12791 if($Level eq "Source")
12792 { # search for a source-compatible equivalent
12793 setAlternative($Symbol, $Level);
12794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012795 }
12796 }
12797}
12798
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012799sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012800{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 my $Level = $_[0];
12802 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803 { # checking added symbols
12804 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012805 next if($CompleteSignature{2}{$Symbol}{"Private"});
12806 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012807 if($Level eq "Binary")
12808 {
12809 if($CompleteSignature{2}{$Symbol}{"InLine"})
12810 {
12811 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12812 { # skip inline non-virtual functions
12813 next;
12814 }
12815 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012816 }
12817 else
12818 { # Source
12819 if($SourceAlternative_B{$Symbol}) {
12820 next;
12821 }
12822 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012823 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012824 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012825 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012826 { # checking removed symbols
12827 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012828 next if($CompleteSignature{1}{$Symbol}{"Private"});
12829 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012830 if($Level eq "Binary")
12831 {
12832 if($CompleteSignature{1}{$Symbol}{"InLine"})
12833 {
12834 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12835 { # skip inline non-virtual functions
12836 next;
12837 }
12838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 }
12840 else
12841 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012842 if(my $Alt = $SourceAlternative{$Symbol})
12843 {
12844 if(defined $CompleteSignature{1}{$Alt}
12845 and $CompleteSignature{1}{$Symbol}{"Const"})
12846 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012847 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012848 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012849 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012850 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012851 }
12852 else
12853 { # do NOT show removed symbol
12854 next;
12855 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012856 }
12857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012858 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012859 }
12860}
12861
12862sub addParamNames($)
12863{
12864 my $LibraryVersion = $_[0];
12865 return if(not keys(%AddIntParams));
12866 my $SecondVersion = $LibraryVersion==1?2:1;
12867 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12868 {
12869 next if(not keys(%{$AddIntParams{$Interface}}));
12870 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012871 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12873 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012874 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012875 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12876 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12877 {
12878 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12879 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12880 }
12881 }
12882 else {
12883 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12884 }
12885 }
12886 }
12887 }
12888}
12889
12890sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012891{ # detect changed typedefs to show
12892 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12894 {
12895 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012896 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12897 if(not $BName1 or isAnon($BName1)) {
12898 next;
12899 }
12900 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12901 if(not $BName2 or isAnon($BName2)) {
12902 next;
12903 }
12904 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012905 $ChangedTypedef{$Typedef} = 1;
12906 }
12907 }
12908}
12909
12910sub get_symbol_suffix($$)
12911{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 my ($Symbol, $Full) = @_;
12913 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012914 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012916 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012917 if(not $Full) {
12918 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12919 }
12920 return $Suffix;
12921}
12922
12923sub get_symbol_prefix($$)
12924{
12925 my ($Symbol, $LibVersion) = @_;
12926 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12927 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12928 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012929 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012930 }
12931 return $ShortName;
12932}
12933
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012935{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012936 my $Symbol = $_[0];
12937 my $PSymbol = $Symbol;
12938 if(not defined $CompleteSignature{2}{$PSymbol}
12939 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12940 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12941 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012942 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012944 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012945 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012946 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12947 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948 {
12949 if(defined $CompleteSignature{2}{$PSymbol}
12950 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12951 {
12952 $SourceAlternative{$Symbol} = $PSymbol;
12953 $SourceAlternative_B{$PSymbol} = $Symbol;
12954 if(not defined $CompleteSignature{1}{$PSymbol}
12955 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12956 $SourceReplacement{$Symbol} = $PSymbol;
12957 }
12958 }
12959 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012960 }
12961 else
12962 {
12963 foreach my $Sp ("KV", "VK", "K", "V")
12964 {
12965 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12966 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12967 {
12968 if(defined $CompleteSignature{2}{$PSymbol}
12969 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12970 {
12971 $SourceAlternative{$Symbol} = $PSymbol;
12972 $SourceAlternative_B{$PSymbol} = $Symbol;
12973 if(not defined $CompleteSignature{1}{$PSymbol}
12974 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12975 $SourceReplacement{$Symbol} = $PSymbol;
12976 }
12977 }
12978 }
12979 $PSymbol = $Symbol;
12980 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012981 }
12982 }
12983 }
12984 return "";
12985}
12986
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012987sub getSymKind($$)
12988{
12989 my ($Symbol, $LibVersion) = @_;
12990 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12991 {
12992 return "Global_Data";
12993 }
12994 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12995 {
12996 return "Method";
12997 }
12998 return "Function";
12999}
13000
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013001sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013002{
13003 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013004 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013005
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013006 mergeBases($Level);
13007
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013008 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013009 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013010 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013011 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013012 next;
13013 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013014 if(defined $CompleteSignature{1}{$Symbol}
13015 and $CompleteSignature{1}{$Symbol}{"Header"})
13016 { # double-check added symbol
13017 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013018 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013019 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013020 next;
13021 }
13022 if($Symbol=~/\A(_Z|\?)/)
13023 { # C++
13024 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13025 }
13026 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13027 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013028 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13029 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013030 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013031 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013032 {
13033 if($TName_Tid{1}{$AffectedClass_Name})
13034 { # class should exist in previous version
13035 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13036 { # old v-table is NOT copied by old applications
13037 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13038 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013039 "Target"=>get_Signature($Symbol, 2),
13040 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013041 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044 }
13045 }
13046 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013047 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13048 { # check all removed exported symbols
13049 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013050 next;
13051 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013052 if(defined $CompleteSignature{2}{$Symbol}
13053 and $CompleteSignature{2}{$Symbol}{"Header"})
13054 { # double-check removed symbol
13055 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013056 }
13057 if($CompleteSignature{1}{$Symbol}{"Private"})
13058 { # skip private methods
13059 next;
13060 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013061 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013062 next;
13063 }
13064 $CheckedSymbols{$Level}{$Symbol} = 1;
13065 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13066 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013067 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13068 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013069 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013070 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13071 {
13072 if($TName_Tid{2}{$AffectedClass_Name})
13073 { # class should exist in newer version
13074 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13075 { # old v-table is NOT copied by old applications
13076 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13077 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013078 "Target"=>get_Signature($OverriddenMethod, 1),
13079 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013080 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013083 }
13084 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013086 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013087 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013088 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013089 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013090 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013091 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013092 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013093 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013094 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013095 {
13096 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13097 "Target"=>$tr_name{$Symbol},
13098 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013099 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013100 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013101 else
13102 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013103 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104 "Target"=>$tr_name{$Symbol},
13105 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013106 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013107 }
13108 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013109 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013110 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013111 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013112 {
13113 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13114 "Target"=>$tr_name{$Symbol},
13115 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013116 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013118 else
13119 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013120 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013121 "Target"=>$tr_name{$Symbol},
13122 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013123 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013124 }
13125 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013126 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13127 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13128 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13129 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13130 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013131 {
13132 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013133 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013134 $ProblemType = "Global_Data_Symbol_Changed_Type";
13135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013136 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13137 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013138 "Old_Type"=>$RTName1,
13139 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013140 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013141 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013142 }
13143 }
13144 }
13145 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013147 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013148 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013149 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013150 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013151 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013152 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13154 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013155 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013156 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013157 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013158 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013159 }
13160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013161 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13162 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013163 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013164 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013165 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013166 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013167 }
13168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013169 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013170 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013171 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013172 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013173 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013174 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013175 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013176 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013177 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013179 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013181 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013184 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013186 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013187 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013188 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013190 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013193 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013194 { # "volatile" to non-"volatile"
13195
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013196 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013197 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013198 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013199 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013200 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013202 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013203 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013205 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013206 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013207 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013208 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013209 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013210 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013211 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013212 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013213 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13214 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013215 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013217 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013218 }
13219 }
13220 }
13221 }
13222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013223 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13224 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013225 $CurrentSymbol = $Symbol;
13226
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013227 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13228 if($Level eq "Source")
13229 { # remove symbol version
13230 $Symbol=$SN;
13231 }
13232 else
13233 { # Binary
13234 if(not $SV)
13235 { # symbol without version
13236 if(my $VSym = $SymVer{1}{$Symbol})
13237 { # the symbol is linked with versioned symbol
13238 if($CompleteSignature{2}{$VSym}{"MnglName"})
13239 { # show report for symbol@ver only
13240 next;
13241 }
13242 elsif(not link_symbol($VSym, 2, "-Deps"))
13243 { # changed version: sym@v1 to sym@v2
13244 # do NOT show report for symbol
13245 next;
13246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013247 }
13248 }
13249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 my $PSymbol = $Symbol;
13251 if($Level eq "Source"
13252 and my $S = $SourceReplacement{$Symbol})
13253 { # take a source-compatible replacement function
13254 $PSymbol = $S;
13255 }
13256 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013257 { # private symbols
13258 next;
13259 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260 if(not defined $CompleteSignature{1}{$Symbol}
13261 or not defined $CompleteSignature{2}{$PSymbol})
13262 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013263 next;
13264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013265 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13266 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13267 { # no mangled name
13268 next;
13269 }
13270 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13271 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013272 { # without a header
13273 next;
13274 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013275
13276 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13277 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13278 { # became pure
13279 next;
13280 }
13281 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13282 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13283 { # became non-pure
13284 next;
13285 }
13286
13287 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13288 { # exported, target, inline virtual and pure virtual
13289 next;
13290 }
13291 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13292 { # exported, target, inline virtual and pure virtual
13293 next;
13294 }
13295
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013296 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013297 {
13298 if($CompleteSignature{1}{$Symbol}{"Data"}
13299 and $CompleteSignature{2}{$PSymbol}{"Data"})
13300 {
13301 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13302 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13303 if(defined $Value1)
13304 {
13305 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13306 if(defined $Value2)
13307 {
13308 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13309 if($Value1 ne $Value2)
13310 {
13311 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13312 "Old_Value"=>$Value1,
13313 "New_Value"=>$Value2,
13314 "Target"=>get_Signature($Symbol, 1) );
13315 }
13316 }
13317 }
13318 }
13319 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013320
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013321 if($CompleteSignature{2}{$PSymbol}{"Private"})
13322 {
13323 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13324 "Target"=>get_Signature_M($PSymbol, 2) );
13325 }
13326 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13327 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13328 {
13329 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13330 "Target"=>get_Signature_M($PSymbol, 2) );
13331 }
13332 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13333 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13334 {
13335 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13336 "Target"=>get_Signature_M($PSymbol, 2) );
13337 }
13338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013339 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013340 mergeVirtualTables($Symbol, $Level);
13341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 if($COMPILE_ERRORS)
13343 { # if some errors occurred at the compiling stage
13344 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 { # missed information about parameters in newer version
13348 next;
13349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013351 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013352 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013353 next;
13354 }
13355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013357 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013359 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13360 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13362 "Target"=>get_Signature($Symbol, 1)
13363 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013365 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013366 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13367 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013368 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 "Target"=>get_Signature($Symbol, 1)
13370 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13373 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013377 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13378 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13379 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013380 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013381 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013382 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13383 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013385 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 my $ProblemType = "Virtual_Method_Position";
13387 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13388 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013390 if(isUsedClass($Class_Id, 1, $Level))
13391 {
13392 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013393 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013394 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013395 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13396 next;
13397 }
13398 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13401 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013402 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013403 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013404 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013406 }
13407 }
13408 }
13409 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13411 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013412 { # do NOT check type changes in pure virtuals
13413 next;
13414 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013415 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 if($Symbol=~/\A(_Z|\?)/
13417 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013421 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013422 }
13423 }
13424 else
13425 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013426 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013427 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013428 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013429 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13430 last if($PType2_Name eq "...");
13431 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13432 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013434 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013435 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013436 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13437 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013438 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13439 $ParamPos_Prev = "lost";
13440 }
13441 }
13442 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013443 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013444 }
13445 if($ParamPos_Prev eq "lost")
13446 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013447 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013448 {
13449 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013450 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013451 $ProblemType = "Added_Unnamed_Parameter";
13452 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013453 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013455 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013456 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013457 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013458 }
13459 else
13460 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013461 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013462 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013463 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013464 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13465 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013466 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013468 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013469 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013470 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013471 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013472 "Param_Type"=>$PType2_Name,
13473 "Old_Value"=>$PName_Old,
13474 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013475 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013476 }
13477 }
13478 else
13479 {
13480 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013481 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013482 $ProblemType = "Added_Middle_Unnamed_Parameter";
13483 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013484 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013485 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013486 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013487 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013488 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013489 }
13490 }
13491 }
13492 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013493 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013494 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013495 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013496 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013497 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013498 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013500 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013502 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13503 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013504 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013505 }
13506 }
13507 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013508 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013509 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013510 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013511 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13512 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013513 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13514 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013516 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013517 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013518 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13519 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13521 $ParamPos_New = "lost";
13522 }
13523 }
13524 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013525 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013526 }
13527 if($ParamPos_New eq "lost")
13528 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013529 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 {
13531 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013532 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 $ProblemType = "Removed_Unnamed_Parameter";
13534 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013535 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013536 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013537 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013538 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013539 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013540 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013541 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013542 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013543 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013544 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013545 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013546 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013547 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013548 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013549 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013550 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013551 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013552 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013553 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013554 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013555 "Old_Value"=>$PName,
13556 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013557 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013558 }
13559 }
13560 else
13561 {
13562 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013563 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13565 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013566 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013567 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013568 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013569 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013570 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013571 }
13572 }
13573 }
13574 }
13575 }
13576 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13578 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013579 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013580
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013581 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013582 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013583 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13584 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013585 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013586
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013587 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013588 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013589 if($SubProblemType eq "Return_Type_And_Size") {
13590 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13591 }
13592 elsif($SubProblemType eq "Return_Type_Format") {
13593 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13594 }
13595 else {
13596 $ProblemTypes{"Global_Data_Type"} = 1;
13597 }
13598
13599 # quals
13600 if($SubProblemType eq "Return_Type"
13601 or $SubProblemType eq "Return_Type_And_Size"
13602 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013603 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013604 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13605 { # const to non-const
13606 if($RR==2) {
13607 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13608 }
13609 else {
13610 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13611 }
13612 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013613 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013614 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13615 { # non-const to const
13616 if($RA==2) {
13617 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13618 }
13619 else {
13620 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13621 }
13622 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013623 }
13624 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013625 }
13626 else
13627 {
13628 # quals
13629 if($SubProblemType eq "Return_Type"
13630 or $SubProblemType eq "Return_Type_And_Size"
13631 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013632 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013633 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013634 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013635 if(addedQual($Old_Value, $New_Value, "volatile"))
13636 {
13637 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13638 if($Level ne "Source"
13639 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13640 $ProblemTypes{"Return_Type"} = 1;
13641 }
13642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013643 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013644 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13645 {
13646 if($RA==2) {
13647 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13648 }
13649 else {
13650 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13651 }
13652 if($Level ne "Source"
13653 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13654 $ProblemTypes{"Return_Type"} = 1;
13655 }
13656 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 }
13658 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013659 if($Level eq "Binary"
13660 and not $CompleteSignature{1}{$Symbol}{"Data"})
13661 {
13662 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13663 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13664 { # if one of the architectures is unknown
13665 # then set other arhitecture to unknown too
13666 ($Arch1, $Arch2) = ("unknown", "unknown");
13667 }
13668 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013669 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013670 {
13671 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13672 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13673 }
13674 else
13675 {
13676 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13677 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13678 }
13679
13680 if($SubProblemType eq "Return_Type_Became_Void")
13681 {
13682 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13683 { # parameters stack has been affected
13684 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013685 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013686 }
13687 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013688 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013689 }
13690 }
13691 }
13692 elsif($SubProblemType eq "Return_Type_From_Void")
13693 {
13694 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13695 { # parameters stack has been affected
13696 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013697 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013698 }
13699 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013700 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013701 }
13702 }
13703 }
13704 elsif($SubProblemType eq "Return_Type"
13705 or $SubProblemType eq "Return_Type_And_Size"
13706 or $SubProblemType eq "Return_Type_Format")
13707 {
13708 if($Conv1{"Method"} ne $Conv2{"Method"})
13709 {
13710 if($Conv1{"Method"} eq "stack")
13711 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013712 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013713 }
13714 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013715 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013716 }
13717 }
13718 else
13719 {
13720 if($Conv1{"Method"} eq "reg")
13721 {
13722 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13723 {
13724 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013725 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013726 }
13727 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013728 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013729 }
13730 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013731 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013732 }
13733 }
13734 }
13735 }
13736 }
13737 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013738
13739 if(not keys(%ProblemTypes))
13740 { # default
13741 $ProblemTypes{$SubProblemType} = 1;
13742 }
13743
13744 foreach my $ProblemType (keys(%ProblemTypes))
13745 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013746 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748 }
13749 if($ReturnType1_Id and $ReturnType2_Id)
13750 {
13751 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013752 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13753
13754 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013755
13756 if($CompleteSignature{1}{$Symbol}{"Data"})
13757 {
13758 if($Level eq "Binary")
13759 {
13760 if(get_PLevel($ReturnType1_Id, 1)==0)
13761 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013762 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013763 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013764
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013765 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13766 {
13767 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013768 {
13769 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13770 {
13771 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13772 last;
13773 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013774 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013775 }
13776 }
13777 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013778 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013779 {
13780 if(defined $GlobalDataObject{1}{$Symbol}
13781 and defined $GlobalDataObject{2}{$Symbol})
13782 {
13783 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13784 my $New_Size = $GlobalDataObject{2}{$Symbol};
13785 if($Old_Size!=$New_Size)
13786 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013787 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013788 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013789 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013790 }
13791 }
13792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 }
13794 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013795
13796 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013797 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013798 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013800 my $NewLocation = "retval";
13801 if($SubLocation and $SubLocation ne "retval") {
13802 $NewLocation = "retval->".$SubLocation;
13803 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013804 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13805 }
13806 }
13807
13808 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13809 {
13810 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13811 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013812 my $NewLocation = "retval";
13813 if($SubLocation and $SubLocation ne "retval") {
13814 $NewLocation = "retval->".$SubLocation;
13815 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013816 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013817 }
13818 }
13819 }
13820
13821 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013822 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13823 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13824 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013825 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013826 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013827 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13828 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013829 if($ThisPtr1_Id and $ThisPtr2_Id)
13830 {
13831 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013832 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13833 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013834 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013835 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013836 {
13837 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013838 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839 }
13840 }
13841 }
13842 }
13843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013844 if($Level eq "Binary") {
13845 mergeVTables($Level);
13846 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013847 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13848 $CheckedSymbols{$Level}{$Symbol} = 1;
13849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013850}
13851
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013852sub rmQuals($$)
13853{
13854 my ($Value, $Qual) = @_;
13855 if(not $Qual) {
13856 return $Value;
13857 }
13858 if($Qual eq "all")
13859 { # all quals
13860 $Qual = "const|volatile|restrict";
13861 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013862 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013863 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013864 }
13865 return $Value;
13866}
13867
13868sub cmpBTypes($$$$)
13869{
13870 my ($T1, $T2, $V1, $V2) = @_;
13871 $T1 = uncover_typedefs($T1, $V1);
13872 $T2 = uncover_typedefs($T2, $V2);
13873 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13874}
13875
13876sub addedQual($$$)
13877{
13878 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013879 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013880}
13881
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013882sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013883{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013884 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013885 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013886}
13887
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013888sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013889{
13890 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13891 $Old_Value = uncover_typedefs($Old_Value, $V1);
13892 $New_Value = uncover_typedefs($New_Value, $V2);
13893 if($Old_Value eq $New_Value)
13894 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013895 return 0;
13896 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013897 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013898 { # without a qual
13899 return 0;
13900 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013901 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013902 { # became non-qual
13903 return 1;
13904 }
13905 else
13906 {
13907 my @BQ1 = getQualModel($Old_Value, $Qual);
13908 my @BQ2 = getQualModel($New_Value, $Qual);
13909 foreach (0 .. $#BQ1)
13910 { # removed qual
13911 if($BQ1[$_]==1
13912 and $BQ2[$_]!=1)
13913 {
13914 return 2;
13915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013916 }
13917 }
13918 return 0;
13919}
13920
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013921sub getQualModel($$)
13922{
13923 my ($Value, $Qual) = @_;
13924 if(not $Qual) {
13925 return $Value;
13926 }
13927
13928 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013929 while($Value=~/(\w+)/ and $1 ne $Qual) {
13930 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013931 }
13932 $Value=~s/[^\*\&\w]+//g;
13933
13934 # modeling
13935 # int*const*const == 011
13936 # int**const == 001
13937 my @Model = ();
13938 my @Elems = split(/[\*\&]/, $Value);
13939 if(not @Elems) {
13940 return (0);
13941 }
13942 foreach (@Elems)
13943 {
13944 if($_ eq $Qual) {
13945 push(@Model, 1);
13946 }
13947 else {
13948 push(@Model, 0);
13949 }
13950 }
13951
13952 return @Model;
13953}
13954
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013955my %StringTypes = map {$_=>1} (
13956 "char*",
13957 "char const*"
13958);
13959
13960my %CharTypes = map {$_=>1} (
13961 "char",
13962 "char const"
13963);
13964
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013965sub showVal($$$)
13966{
13967 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013968 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013969 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013970 if(substr($Value, 0, 2) eq "_Z")
13971 {
13972 if(my $Unmangled = $tr_name{$Value}) {
13973 return $Unmangled;
13974 }
13975 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013976 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013977 { # strings
13978 return "\"$Value\"";
13979 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013980 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013981 { # characters
13982 return "\'$Value\'";
13983 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013984 if($Value eq "")
13985 { # other
13986 return "\'\'";
13987 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013988 return $Value;
13989}
13990
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013991sub getRegs($$$)
13992{
13993 my ($LibVersion, $Symbol, $Pos) = @_;
13994
13995 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13996 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013997 my %Regs = ();
13998 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13999 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014000 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014001 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14002 }
14003 }
14004
14005 return join(", ", sort keys(%Regs));
14006 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014007 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14008 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14009 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14010 {
14011 return "unknown";
14012 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014013
14014 return undef;
14015}
14016
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014017sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014018{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014019 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014020 if(not $Symbol) {
14021 return;
14022 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014023 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14024 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14025 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14026 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014027 if(not $PType1_Id
14028 or not $PType2_Id) {
14029 return;
14030 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014031
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014032 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014033 { # do not merge "this"
14034 if($PName1 eq "this" or $PName2 eq "this") {
14035 return;
14036 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014037 }
14038
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014039 my %Type1 = get_Type($PType1_Id, 1);
14040 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014041
14042 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14043
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014044 my %BaseType1 = get_BaseType($PType1_Id, 1);
14045 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014046
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014047 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014048
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014049 if($Level eq "Binary")
14050 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014051 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014052 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14053 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14054 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14055 {
14056 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014057 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014058 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014059 }
14060 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14061 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14062 {
14063 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014064 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014065 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014066 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014067 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014068
14069 if(defined $UsedDump{1}{"DWARF"}
14070 and defined $UsedDump{2}{"DWARF"})
14071 {
14072 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14073 {
14074 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14075 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014076
14077 if($Old_Regs ne "unknown"
14078 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014079 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014080 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014081 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014082 if($Old_Regs ne $New_Regs)
14083 {
14084 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14085 "Target"=>$PName1,
14086 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14087 "Old_Value"=>$Old_Regs,
14088 "New_Value"=>$New_Regs );
14089 }
14090 }
14091 elsif($Old_Regs and not $New_Regs)
14092 {
14093 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014094 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014095 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014096 "Old_Value"=>$Old_Regs );
14097 }
14098 elsif(not $Old_Regs and $New_Regs)
14099 {
14100 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14101 "Target"=>$PName1,
14102 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014103 "New_Value"=>$New_Regs );
14104 }
14105 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014106
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014107 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14108 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14109 {
14110 if($Old_Offset ne $New_Offset)
14111 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014112 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14113 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14114
14115 $Old_Offset = $Old_Offset - $Start1;
14116 $New_Offset = $New_Offset - $Start2;
14117
14118 if($Old_Offset ne $New_Offset)
14119 {
14120 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14121 "Target"=>$PName1,
14122 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14123 "Old_Value"=>$Old_Offset,
14124 "New_Value"=>$New_Offset );
14125 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014126 }
14127 }
14128 }
14129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014130 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014131 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14132 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014133 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014134 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014135 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14136 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014137 if(not checkDump(1, "2.13")
14138 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014139 { # support for old ABI dumps
14140 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014141 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014142 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014143 and $Value_Old eq "false" and $Value_New eq "0")
14144 { # int class::method ( bool p = 0 );
14145 # old ABI dumps: "false"
14146 # new ABI dumps: "0"
14147 $Value_Old = "0";
14148 }
14149 }
14150 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014151 if(not checkDump(1, "2.18")
14152 and checkDump(2, "2.18"))
14153 { # support for old ABI dumps
14154 if(not defined $Value_Old
14155 and substr($Value_New, 0, 2) eq "_Z") {
14156 $Value_Old = $Value_New;
14157 }
14158 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014159 if(defined $Value_Old)
14160 {
14161 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14162 if(defined $Value_New)
14163 {
14164 $Value_New = showVal($Value_New, $PType2_Id, 2);
14165 if($Value_Old ne $Value_New)
14166 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014167 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014168 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014169 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014170 "Old_Value"=>$Value_Old,
14171 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014172 }
14173 }
14174 else
14175 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014176 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014178 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014179 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014180 }
14181 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182 elsif(defined $Value_New)
14183 {
14184 $Value_New = showVal($Value_New, $PType2_Id, 2);
14185 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14186 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014187 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014188 "New_Value"=>$Value_New );
14189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014190 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014191
14192 if($ChkRnmd)
14193 {
14194 if($PName1 and $PName2 and $PName1 ne $PName2
14195 and $PType1_Id!=-1 and $PType2_Id!=-1
14196 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14197 { # except unnamed "..." value list (Id=-1)
14198 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14199 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014200 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014201 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14202 "Old_Value"=>$PName1,
14203 "New_Value"=>$PName2,
14204 "New_Signature"=>get_Signature($Symbol, 2) );
14205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014206 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014207
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014208 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014209 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014211 foreach my $SubProblemType (keys(%SubProblems))
14212 { # add new problems, remove false alarms
14213 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14214 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014215
14216 # quals
14217 if($SubProblemType eq "Parameter_Type"
14218 or $SubProblemType eq "Parameter_Type_And_Size"
14219 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014220 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014221 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014222 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014223 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014224 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014225 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014226 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14227 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14228 }
14229 }
14230 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14231 {
14232 if(removedQual($Old_Value, $New_Value, "volatile")) {
14233 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014234 }
14235 }
14236 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14237 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14238 { # int to "int const"
14239 delete($SubProblems{$SubProblemType});
14240 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014241 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014242 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14243 { # "int const" to int
14244 delete($SubProblems{$SubProblemType});
14245 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014246 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14247 { # "const" to non-"const"
14248 if($RR==2) {
14249 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14250 }
14251 else {
14252 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14253 }
14254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014255 }
14256 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014257
14258 if($Level eq "Source")
14259 {
14260 foreach my $SubProblemType (keys(%SubProblems))
14261 {
14262 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14263 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14264
14265 if($SubProblemType eq "Parameter_Type")
14266 {
14267 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14268 delete($SubProblems{$SubProblemType});
14269 }
14270 }
14271 }
14272 }
14273
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014274 foreach my $SubProblemType (keys(%SubProblems))
14275 { # modify/register problems
14276 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14277 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014278 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14279 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014281 my $NewProblemType = $SubProblemType;
14282 if($Old_Value eq "..." and $New_Value ne "...")
14283 { # change from "..." to "int"
14284 if($ParamPos1==0)
14285 { # ISO C requires a named argument before "..."
14286 next;
14287 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014288 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014289 }
14290 elsif($New_Value eq "..." and $Old_Value ne "...")
14291 { # change from "int" to "..."
14292 if($ParamPos2==0)
14293 { # ISO C requires a named argument before "..."
14294 next;
14295 }
14296 $NewProblemType = "Parameter_Became_VaList";
14297 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014298 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014299 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014300 {
14301 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014302 if($Arch1 eq "unknown"
14303 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014304 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014305 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014306 ($Arch1, $Arch2) = ("unknown", "unknown");
14307 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014308 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014309 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014310 { # real
14311 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14312 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14313 }
14314 else
14315 { # model
14316 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14317 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14318 }
14319 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014320 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014321 if($Conv1{"Method"} eq "stack")
14322 {
14323 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14324 $NewProblemType = "Parameter_Type_And_Stack";
14325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014326 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014327 elsif($Conv1{"Method"} eq "reg")
14328 {
14329 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14330 $NewProblemType = "Parameter_Type_And_Register";
14331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014332 }
14333 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014334 elsif($Conv1{"Method"} ne "unknown"
14335 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014336 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014337 if($Conv1{"Method"} eq "stack") {
14338 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014339 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014340 elsif($Conv1{"Method"} eq "register") {
14341 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014342 }
14343 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014344 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14345 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014347 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014348 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014349 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014350 "New_Signature"=>get_Signature($Symbol, 2) );
14351 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014354 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014355
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014356 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014357 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14358 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014360 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014361 {
14362 my $NewProblemType = $SubProblemType;
14363 if($SubProblemType eq "DataType_Size")
14364 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014365 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 { # stack has been affected
14367 $NewProblemType = "DataType_Size_And_Stack";
14368 }
14369 }
14370 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014371 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014372 }
14373 }
14374}
14375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376sub find_ParamPair_Pos_byName($$$)
14377{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014378 my ($Name, $Symbol, $LibVersion) = @_;
14379 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014380 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014381 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14382 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014383 {
14384 return $ParamPos;
14385 }
14386 }
14387 return "lost";
14388}
14389
14390sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14391{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014392 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014393 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014394 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014395 {
14396 next if($Order eq "backward" and $ParamPos>$MediumPos);
14397 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014398 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14399 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014400 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014401 push(@Positions, $ParamPos);
14402 }
14403 }
14404 return @Positions;
14405}
14406
14407sub getTypeIdByName($$)
14408{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014409 my ($TypeName, $LibVersion) = @_;
14410 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411}
14412
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014413sub diffTypes($$$)
14414{
14415 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14416 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14417 }
14418 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14419 { # skip recursive declarations
14420 return 0;
14421 }
14422
14423 pushType($_[0], $_[1], \@RecurTypes_Diff);
14424 my $Diff = diffTypes_I(@_);
14425 pop(@RecurTypes_Diff);
14426
14427 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14428}
14429
14430sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014431{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014432 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014433
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014434 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14435 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014437 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14438 { # equal types
14439 return 0;
14440 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014441 if($Type1_Pure{"Name"} eq "void")
14442 { # from void* to something
14443 return 0;
14444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014445 if($Type1_Pure{"Name"}=~/\*/
14446 or $Type2_Pure{"Name"}=~/\*/)
14447 { # compared in detectTypeChange()
14448 return 0;
14449 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014451 my %FloatType = map {$_=>1} (
14452 "float",
14453 "double",
14454 "long double"
14455 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014456
14457 my $T1 = $Type1_Pure{"Type"};
14458 my $T2 = $Type2_Pure{"Type"};
14459
14460 if($T1 eq "Struct"
14461 and $T2 eq "Class")
14462 { # compare as data structures
14463 $T2 = "Struct";
14464 }
14465
14466 if($T1 eq "Class"
14467 and $T2 eq "Struct")
14468 { # compare as data structures
14469 $T1 = "Struct";
14470 }
14471
14472 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014473 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014474 if($T1 eq "Intrinsic"
14475 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 { # "int" to "enum"
14477 return 0;
14478 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014479 elsif($T2 eq "Intrinsic"
14480 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014481 { # "enum" to "int"
14482 return 0;
14483 }
14484 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014485 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014486 # ...
14487 return 1;
14488 }
14489 }
14490 else
14491 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014492 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014493 {
14494 if($FloatType{$Type1_Pure{"Name"}}
14495 or $FloatType{$Type2_Pure{"Name"}})
14496 { # "float" to "double"
14497 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014498 if($Level eq "Source")
14499 { # Safe
14500 return 0;
14501 }
14502 else {
14503 return 1;
14504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014505 }
14506 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014507 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508 {
14509 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14510 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014511 if(not @Membs1
14512 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014513 { # private
14514 return 0;
14515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014516 if($#Membs1!=$#Membs2)
14517 { # different number of elements
14518 return 1;
14519 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014520 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 {
14522 foreach my $Pos (@Membs1)
14523 { # compare elements by name and value
14524 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14525 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14526 { # different names
14527 return 1;
14528 }
14529 }
14530 }
14531 else
14532 {
14533 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014534 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014535 if($Level eq "Source")
14536 {
14537 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14538 { # different names
14539 return 1;
14540 }
14541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014542
14543 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14544 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14545
14546 if($MT1{"Name"} ne $MT2{"Name"}
14547 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14548 {
14549 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14550 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14551
14552 if($PL1 ne $PL2)
14553 { # different pointer level
14554 return 1;
14555 }
14556
14557 # compare base types
14558 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14559 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14560
14561 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14562 { # different types
14563 return 1;
14564 }
14565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014566 }
14567 }
14568 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014569 else
14570 {
14571 # TODO: arrays, etc.
14572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 }
14574 return 0;
14575}
14576
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014577sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014578{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014579 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014580 if(not $Type1_Id or not $Type2_Id) {
14581 return ();
14582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014584 my %Type1 = get_Type($Type1_Id, 1);
14585 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014586 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14587 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14588 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14589 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 +040014590
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014591 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14592 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14594 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14595 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14596 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14597 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14598 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14599 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014600 if($Type1{"Name"} eq $Type2{"Name"})
14601 {
14602 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14603 { # will be reported in mergeTypes() as typedef problem
14604 return ();
14605 }
14606 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14607 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14608 if(%Typedef_1 and %Typedef_2)
14609 {
14610 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14611 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14612 { # const Typedef
14613 return ();
14614 }
14615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616 }
14617 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014619 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014620 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14621 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014622 {
14623 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14624 "Old_Value"=>$Type1_Base{"Name"},
14625 "New_Value"=>$Type2_Base{"Name"},
14626 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014627 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 }
14629 else
14630 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014631 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014632 { # format change
14633 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14634 "Old_Value"=>$Type1_Base{"Name"},
14635 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014636 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014637 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014638 }
14639 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14640 {
14641 %{$LocalProblems{$Prefix."_BaseType"}}=(
14642 "Old_Value"=>$Type1_Base{"Name"},
14643 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014644 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014645 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014646 }
14647 }
14648 }
14649 }
14650 elsif($Type1{"Name"} ne $Type2{"Name"})
14651 { # type change
14652 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14653 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014654 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014655 and $Type1_Pure{"Name"} eq "void")
14656 {
14657 %{$LocalProblems{"Return_Type_From_Void"}}=(
14658 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014659 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014661 elsif($Prefix eq "Return"
14662 and $Type2_Pure{"Name"} eq "void")
14663 {
14664 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14665 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014666 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014667 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014668 else
14669 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014670 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014671 and $Type1{"Size"} and $Type2{"Size"}
14672 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014673 {
14674 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14675 "Old_Value"=>$Type1{"Name"},
14676 "New_Value"=>$Type2{"Name"},
14677 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014678 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679 }
14680 else
14681 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014682 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014683 { # format change
14684 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14685 "Old_Value"=>$Type1{"Name"},
14686 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014687 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014688 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014689 }
14690 elsif(tNameLock($Type1_Id, $Type2_Id))
14691 { # FIXME: correct this condition
14692 %{$LocalProblems{$Prefix."_Type"}}=(
14693 "Old_Value"=>$Type1{"Name"},
14694 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014695 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014696 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014697 }
14698 }
14699 }
14700 }
14701 }
14702 if($Type1_PLevel!=$Type2_PLevel)
14703 {
14704 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14705 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14706 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014707 if($Level eq "Source")
14708 {
14709 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710 "Old_Value"=>$Type1_PLevel,
14711 "New_Value"=>$Type2_PLevel);
14712 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014713 else
14714 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014715 if($Type2_PLevel>$Type1_PLevel)
14716 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014717 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14718 "Old_Value"=>$Type1_PLevel,
14719 "New_Value"=>$Type2_PLevel);
14720 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014721 else
14722 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014723 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14724 "Old_Value"=>$Type1_PLevel,
14725 "New_Value"=>$Type2_PLevel);
14726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014727 }
14728 }
14729 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014730 if($Type1_Pure{"Type"} eq "Array"
14731 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014732 { # base_type[N] -> base_type[N]
14733 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014734 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 foreach my $SubProblemType (keys(%SubProblems))
14736 {
14737 $SubProblemType=~s/_Type/_BaseType/g;
14738 next if(defined $LocalProblems{$SubProblemType});
14739 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14740 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14741 }
14742 }
14743 }
14744 return %LocalProblems;
14745}
14746
14747sub tNameLock($$)
14748{
14749 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014750 my $Changed = 0;
14751 if(differentDumps("G"))
14752 { # different GCC versions
14753 $Changed = 1;
14754 }
14755 elsif(differentDumps("V"))
14756 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014757 if(not checkDump(1, "2.20")
14758 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014759 { # latest names update
14760 # 2.6: added restrict qualifier
14761 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014762 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014763 $Changed = 1;
14764 }
14765 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014766
14767 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14768 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14769
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014770 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14771 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14772
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014773 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014774 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014775 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014776 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014777 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014778 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014779 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014780 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014781 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014782 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014783 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14784 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14785 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014786 { # equal base types
14787 return 0;
14788 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014789
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014790 if(not checkDump(1, "2.13")
14791 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014792 { # broken array names in ABI dumps < 2.13
14793 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014794 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014795 return 0;
14796 }
14797 }
14798
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014799 if(not checkDump(1, "2.6")
14800 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014801 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014802 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014803 and $TN2=~/\brestrict\b/) {
14804 return 0;
14805 }
14806 }
14807
14808 if(not checkDump(1, "2.20")
14809 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014810 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014811 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14812 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014813 return 0;
14814 }
14815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014816 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014817 else
14818 {
14819 # typedef struct {...} type_t
14820 # typedef struct type_t {...} type_t
14821 if(index($TN1, " ".$TN2)!=-1)
14822 {
14823 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14824 return 0;
14825 }
14826 }
14827 if(index($TN2, " ".$TN1)!=-1)
14828 {
14829 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14830 return 0;
14831 }
14832 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014833
14834 if($TT1 eq "FuncPtr"
14835 and $TT2 eq "FuncPtr")
14836 {
14837 my $TN1_C = $TN1;
14838 my $TN2_C = $TN2;
14839
14840 $TN1_C=~s/\b(struct|union) //g;
14841 $TN2_C=~s/\b(struct|union) //g;
14842
14843 if($TN1_C eq $TN2_C) {
14844 return 0;
14845 }
14846 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014847 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014848
14849 my ($N1, $N2) = ($TN1, $TN2);
14850 $N1=~s/\b(struct|union) //g;
14851 $N2=~s/\b(struct|union) //g;
14852
14853 if($N1 eq $N2)
14854 { # QList<struct QUrl> and QList<QUrl>
14855 return 0;
14856 }
14857
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014858 return 1;
14859}
14860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014861sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014862{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014863 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014864 if(defined $Cache{"differentDumps"}{$Check}) {
14865 return $Cache{"differentDumps"}{$Check};
14866 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014867 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014868 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014869 if($Check eq "G")
14870 {
14871 if(getGccVersion(1) ne getGccVersion(2))
14872 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014873 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014875 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014876 if($Check eq "V")
14877 {
14878 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14879 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14880 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014881 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014882 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014884 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014885 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014886}
14887
14888sub formatVersion($$)
14889{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014890 my ($V, $Digits) = @_;
14891 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014892 return join(".", splice(@Elems, 0, $Digits));
14893}
14894
14895sub htmlSpecChars($)
14896{
14897 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014898 if(not $Str) {
14899 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014901 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14902 $Str=~s/</&lt;/g;
14903 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14904 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014905 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14906 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014907 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014908 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014909 $Str=~s/\n/<br\/>/g;
14910 $Str=~s/\"/&quot;/g;
14911 $Str=~s/\'/&#39;/g;
14912 return $Str;
14913}
14914
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014915sub xmlSpecChars($)
14916{
14917 my $Str = $_[0];
14918 if(not $Str) {
14919 return $Str;
14920 }
14921
14922 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14923 $Str=~s/</&lt;/g;
14924 $Str=~s/>/&gt;/g;
14925
14926 $Str=~s/\"/&quot;/g;
14927 $Str=~s/\'/&#39;/g;
14928
14929 return $Str;
14930}
14931
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014932sub xmlSpecChars_R($)
14933{
14934 my $Str = $_[0];
14935 if(not $Str) {
14936 return $Str;
14937 }
14938
14939 $Str=~s/&amp;/&/g;
14940 $Str=~s/&lt;/</g;
14941 $Str=~s/&gt;/>/g;
14942
14943 $Str=~s/&quot;/"/g;
14944 $Str=~s/&#39;/'/g;
14945
14946 return $Str;
14947}
14948
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949sub black_name($)
14950{
14951 my $Name = $_[0];
14952 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14953}
14954
14955sub highLight_Signature($)
14956{
14957 my $Signature = $_[0];
14958 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14959}
14960
14961sub highLight_Signature_Italic_Color($)
14962{
14963 my $Signature = $_[0];
14964 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14965}
14966
14967sub separate_symbol($)
14968{
14969 my $Symbol = $_[0];
14970 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14971 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14972 ($Name, $Spec, $Ver) = ($1, $2, $3);
14973 }
14974 return ($Name, $Spec, $Ver);
14975}
14976
14977sub cut_f_attrs($)
14978{
14979 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14980 return $2;
14981 }
14982 return "";
14983}
14984
14985sub highLight_Signature_PPos_Italic($$$$$)
14986{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014987 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14988 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014989 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14990 my $Return = "";
14991 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14992 $Return = $2;
14993 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014994 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014995 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014996 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014998 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014999 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015001 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015002 }
15003 return $Signature;
15004 }
15005 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15006 $Begin.=" " if($Begin!~/ \Z/);
15007 $End = cut_f_attrs($Signature);
15008 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015009 my ($Short, $Params) = split_Signature($Signature);
15010 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015011 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015012 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015013 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015014 $Part=~s/\A\s+|\s+\Z//g;
15015 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15016 if($Part=~/\([\*]+(\w+)\)/i) {
15017 $ParamName = $1;#func-ptr
15018 }
15019 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15020 $ParamName = $1;
15021 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015022 if(not $ParamName)
15023 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015024 push(@Parts, $Part_Styled);
15025 next;
15026 }
15027 if($ItalicParams and not $TName_Tid{1}{$Part}
15028 and not $TName_Tid{2}{$Part})
15029 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015030 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015031 if($Param_Pos ne ""
15032 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015033 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015034 }
15035 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015036 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015037 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015038 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 }
15040 $Part_Styled=~s/,(\w)/, $1/g;
15041 push(@Parts, $Part_Styled);
15042 }
15043 if(@Parts)
15044 {
15045 foreach my $Num (0 .. $#Parts)
15046 {
15047 if($Num==$#Parts)
15048 { # add ")" to the last parameter
15049 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15050 }
15051 elsif(length($Parts[$Num])<=45) {
15052 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15053 }
15054 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015055 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015056 }
15057 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015058 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015059 }
15060 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015061 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015062 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015063 $Signature=~s!\[\]![&#160;]!g;
15064 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015065 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15066 if($SymbolVersion) {
15067 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15068 }
15069 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070}
15071
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015072sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015073{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015074 my $Signature = $_[0];
15075 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15076 {
15077 $Signature=~s/\A\Q$ShortName\E\(//g;
15078 cut_f_attrs($Signature);
15079 $Signature=~s/\)\Z//;
15080 return ($ShortName, $Signature);
15081 }
15082
15083 # error
15084 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015085}
15086
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015087sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015088{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015089 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015090 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015091 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15092 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093 foreach my $Pos (0 .. length($Params) - 1)
15094 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015095 my $S = substr($Params, $Pos, 1);
15096 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015097 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015098 }
15099 if($S eq "," and
15100 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015102 if($Comma)
15103 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015104 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015105 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015106 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015107 }
15108 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015109 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015110 }
15111 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015112 if(not $Sp)
15113 { # remove spaces
15114 foreach (@Parts)
15115 {
15116 s/\A //g;
15117 s/ \Z//g;
15118 }
15119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015120 return @Parts;
15121}
15122
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015123sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015124{
15125 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015126 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015127 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015128 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15129 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 $Center+=length($1);
15131 }
15132 foreach my $Pos (0 .. length($Sign)-1)
15133 {
15134 my $S = substr($Sign, $Pos, 1);
15135 if($S eq $Target)
15136 {
15137 if($B{"("}==$B{")"}
15138 and $B{"<"}==$B{">"}) {
15139 return $Center;
15140 }
15141 }
15142 if(defined $B{$S}) {
15143 $B{$S}+=1;
15144 }
15145 $Center+=1;
15146 }
15147 return 0;
15148}
15149
15150sub appendFile($$)
15151{
15152 my ($Path, $Content) = @_;
15153 return if(not $Path);
15154 if(my $Dir = get_dirname($Path)) {
15155 mkpath($Dir);
15156 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015157 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015158 print FILE $Content;
15159 close(FILE);
15160}
15161
15162sub writeFile($$)
15163{
15164 my ($Path, $Content) = @_;
15165 return if(not $Path);
15166 if(my $Dir = get_dirname($Path)) {
15167 mkpath($Dir);
15168 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015169 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170 print FILE $Content;
15171 close(FILE);
15172}
15173
15174sub readFile($)
15175{
15176 my $Path = $_[0];
15177 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015178 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015179 local $/ = undef;
15180 my $Content = <FILE>;
15181 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015182 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015183 $Content=~s/\r/\n/g;
15184 }
15185 return $Content;
15186}
15187
15188sub get_filename($)
15189{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015190 if(defined $Cache{"get_filename"}{$_[0]}) {
15191 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015192 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015193 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15194 return ($Cache{"get_filename"}{$_[0]}=$1);
15195 }
15196 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015197}
15198
15199sub get_dirname($)
15200{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015201 if(defined $Cache{"get_dirname"}{$_[0]}) {
15202 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015204 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15205 return ($Cache{"get_dirname"}{$_[0]}=$1);
15206 }
15207 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015208}
15209
15210sub separate_path($) {
15211 return (get_dirname($_[0]), get_filename($_[0]));
15212}
15213
15214sub esc($)
15215{
15216 my $Str = $_[0];
15217 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15218 return $Str;
15219}
15220
15221sub readLineNum($$)
15222{
15223 my ($Path, $Num) = @_;
15224 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015225 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015226 foreach (1 ... $Num) {
15227 <FILE>;
15228 }
15229 my $Line = <FILE>;
15230 close(FILE);
15231 return $Line;
15232}
15233
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015234sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015235{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015236 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 return () if(not $Path or not -f $Path);
15238 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015239 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15240 {
15241 foreach my $AttrVal (split(/;/, $1))
15242 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 if($AttrVal=~/(.+):(.+)/)
15244 {
15245 my ($Name, $Value) = ($1, $2);
15246 $Attributes{$Name} = $Value;
15247 }
15248 }
15249 }
15250 return \%Attributes;
15251}
15252
15253sub is_abs($) {
15254 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15255}
15256
15257sub get_abs_path($)
15258{ # abs_path() should NOT be called for absolute inputs
15259 # because it can change them
15260 my $Path = $_[0];
15261 if(not is_abs($Path)) {
15262 $Path = abs_path($Path);
15263 }
15264 return $Path;
15265}
15266
15267sub get_OSgroup()
15268{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015269 my $N = $Config{"osname"};
15270 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 return "macos";
15272 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015273 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274 return "bsd";
15275 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015276 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015277 return "beos";
15278 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015279 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015280 return "symbian";
15281 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015282 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015283 return "windows";
15284 }
15285 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015286 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287 }
15288}
15289
15290sub getGccVersion($)
15291{
15292 my $LibVersion = $_[0];
15293 if($GCC_VERSION{$LibVersion})
15294 { # dump version
15295 return $GCC_VERSION{$LibVersion};
15296 }
15297 elsif($UsedDump{$LibVersion}{"V"})
15298 { # old-version dumps
15299 return "unknown";
15300 }
15301 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15302 if(not $GccVersion) {
15303 return "unknown";
15304 }
15305 return $GccVersion;
15306}
15307
15308sub showArch($)
15309{
15310 my $Arch = $_[0];
15311 if($Arch eq "arm"
15312 or $Arch eq "mips") {
15313 return uc($Arch);
15314 }
15315 return $Arch;
15316}
15317
15318sub getArch($)
15319{
15320 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015321
15322 if($TargetArch) {
15323 return $TargetArch;
15324 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015325 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015326 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015327 return $CPU_ARCH{$LibVersion};
15328 }
15329 elsif($UsedDump{$LibVersion}{"V"})
15330 { # old-version dumps
15331 return "unknown";
15332 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015333
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015334 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015335}
15336
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015337sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015338{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015339 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015341 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015342 if(getArch(1) ne getArch(2)
15343 or getArch(1) eq "unknown"
15344 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015345 { # don't show architecture in the header
15346 $ArchInfo="";
15347 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015348 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015349 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015350 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015351 }
15352 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015353 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015354 }
15355 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015356 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015357 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015358
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015359 my $V1 = $Descriptor{1}{"Version"};
15360 my $V2 = $Descriptor{2}{"Version"};
15361
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015362 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15363 {
15364 my $M1 = $UsedDump{1}{"M"};
15365 my $M2 = $UsedDump{2}{"M"};
15366
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015367 my $M1S = $M1;
15368 my $M2S = $M2;
15369
15370 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15371 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15372
15373 if($M1S eq $M2S
15374 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015375 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015376 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15377 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015378 }
15379 else
15380 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015381 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15382 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015383 }
15384 }
15385 else
15386 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015387 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015388 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015389 }
15390
15391 $Title .= $ArchInfo;
15392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015393 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015394 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015395 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015396 $Title = "<h1>".$Title."</h1>\n";
15397 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398}
15399
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015400sub get_CheckedHeaders($)
15401{
15402 my $LibVersion = $_[0];
15403
15404 my @Headers = ();
15405
15406 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15407 {
15408 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015409
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015410 if(not is_target_header($File, $LibVersion)) {
15411 next;
15412 }
15413
15414 if(skipHeader($File, $LibVersion)) {
15415 next;
15416 }
15417
15418 push(@Headers, $Path);
15419 }
15420
15421 return @Headers;
15422}
15423
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015424sub get_SourceInfo()
15425{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015426 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015427
15428 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015429 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015430 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15431 $CheckedHeaders .= "<div class='h_list'>\n";
15432 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 +040015433 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015434 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15435 my $Name = get_filename($Identity);
15436 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15437 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015438 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015439 $CheckedHeaders .= "</div>\n";
15440 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015441 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015442
15443 if(my @Sources = keys(%{$Registered_Sources{1}}))
15444 {
15445 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15446 $CheckedSources .= "<div class='h_list'>\n";
15447 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15448 {
15449 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15450 my $Name = get_filename($Identity);
15451 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15452 $CheckedSources .= $Name.$Comment."<br/>\n";
15453 }
15454 $CheckedSources .= "</div>\n";
15455 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15456 }
15457
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015458 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015459 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015460 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015461 $CheckedLibs .= "<div class='lib_list'>\n";
15462 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15463 {
15464 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15465 $CheckedLibs .= $Library."<br/>\n";
15466 }
15467 $CheckedLibs .= "</div>\n";
15468 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015469 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015470
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015471 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15472}
15473
15474sub get_ObjTitle()
15475{
15476 if(defined $UsedDump{1}{"DWARF"}) {
15477 return "Objects";
15478 }
15479 else {
15480 return ucfirst($SLIB_TYPE)." Libraries";
15481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482}
15483
15484sub get_TypeProblems_Count($$$)
15485{
15486 my ($TypeChanges, $TargetPriority, $Level) = @_;
15487 my $Type_Problems_Count = 0;
15488 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15489 {
15490 my %Kinds_Target = ();
15491 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15492 {
15493 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15494 {
15495 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015496 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15497 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015498 if($Kinds_Target{$Kind}{$Target}) {
15499 next;
15500 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015501
15502 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15503 {
15504 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15505 { # select a problem with the highest priority
15506 next;
15507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015508 }
15509 $Kinds_Target{$Kind}{$Target} = 1;
15510 $Type_Problems_Count += 1;
15511 }
15512 }
15513 }
15514 return $Type_Problems_Count;
15515}
15516
15517sub get_Summary($)
15518{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015519 my $Level = $_[0];
15520 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015521 $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 +040015522 %{$RESULT{$Level}} = (
15523 "Problems"=>0,
15524 "Warnings"=>0,
15525 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015526 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015527 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015528 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015529 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015530 {
15531 if(not defined $CompatRules{$Level}{$Kind})
15532 { # unknown rule
15533 if(not $UnknownRules{$Level}{$Kind})
15534 { # only one warning
15535 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15536 $UnknownRules{$Level}{$Kind}=1;
15537 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015538 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 }
15540 }
15541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015542 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15543 {
15544 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15545 {
15546 if(not defined $CompatRules{$Level}{$Kind})
15547 { # unknown rule
15548 if(not $UnknownRules{$Level}{$Kind})
15549 { # only one warning
15550 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15551 $UnknownRules{$Level}{$Kind}=1;
15552 }
15553 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15554 }
15555 }
15556 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015557 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015558 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015559 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015560 {
15561 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015563 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015564 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015565 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015566 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015567 $Added += 1;
15568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015569 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015570 {
15571 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015572 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015573 }
15574 else
15575 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015576 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015577 $I_Other += 1;
15578 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015579 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 $I_Problems_High += 1;
15581 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015582 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015583 $I_Problems_Medium += 1;
15584 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015585 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 $I_Problems_Low += 1;
15587 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015588 if(($Severity ne "Low" or $StrictCompat)
15589 and $Severity ne "Safe") {
15590 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015591 }
15592 }
15593 }
15594 }
15595 }
15596 }
15597 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015598 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015599 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015600 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015601 {
15602 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15603 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015604 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015605 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015606 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15607 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015608 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015609 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15610
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015611 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015612 { # select a problem with the highest priority
15613 next;
15614 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015615
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015616 if(($Severity ne "Low" or $StrictCompat)
15617 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015618 {
15619 if(defined $TotalAffected{$Level}{$Interface})
15620 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015621 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15622 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015623 }
15624 }
15625 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015626 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015628 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015629
15630 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15631
15632 if($MaxSeverity)
15633 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015634 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15635 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015636 }
15637 }
15638 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015639 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015641 }
15642 }
15643 }
15644 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015645
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015646 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15647 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15648 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15649 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015650
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015651 %TypeChanges = (); # free memory
15652
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015653 # changed and removed public symbols
15654 my $SCount = keys(%{$CheckedSymbols{$Level}});
15655 if($ExtendedCheck)
15656 { # don't count external_func_0 for constants
15657 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015659 if($SCount)
15660 {
15661 my %Weight = (
15662 "High" => 100,
15663 "Medium" => 50,
15664 "Low" => 25
15665 );
15666 foreach (keys(%{$TotalAffected{$Level}})) {
15667 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015668 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015669 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015670 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015671 else {
15672 $RESULT{$Level}{"Affected"} = 0;
15673 }
15674
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015675 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15676 if($RESULT{$Level}{"Affected"}>=100) {
15677 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015678 }
15679
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015680 $RESULT{$Level}{"Problems"} += $Removed;
15681 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015682 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015683 if($StrictCompat) {
15684 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15685 }
15686 else {
15687 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015689
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015690 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015691 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015692 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015693 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015694 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015695 if($Severity eq "Safe")
15696 {
15697 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015698 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015699 elsif($Severity eq "Low")
15700 {
15701 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015702 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015703 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015704 }
15705
15706 if($C_Problems_Low)
15707 {
15708 if($StrictCompat) {
15709 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15710 }
15711 else {
15712 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015713 }
15714 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015715 if($RESULT{$Level}{"Problems"}
15716 and $RESULT{$Level}{"Affected"}) {
15717 $RESULT{$Level}{"Verdict"} = "incompatible";
15718 }
15719 else {
15720 $RESULT{$Level}{"Verdict"} = "compatible";
15721 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015722
15723 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15724 if(not $TotalTypes)
15725 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015726 $TotalTypes = keys(%{$TName_Tid{1}});
15727 }
15728
15729 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15730 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15731
15732 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15733
15734 if($ReportFormat eq "xml")
15735 { # XML
15736 # test info
15737 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15738 $TestInfo .= " <version1>\n";
15739 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015740 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015741 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15742 $TestInfo .= " </version1>\n";
15743
15744 $TestInfo .= " <version2>\n";
15745 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015746 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015747 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15748 $TestInfo .= " </version2>\n";
15749 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15750
15751 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015752 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015753 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015754 $TestResults .= " <headers>\n";
15755 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15756 {
15757 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15758 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15759 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15760 }
15761 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015762 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015763
15764 if(my @Sources = keys(%{$Registered_Sources{1}}))
15765 {
15766 $TestResults .= " <sources>\n";
15767 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15768 {
15769 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15770 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15771 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15772 }
15773 $TestResults .= " </sources>\n";
15774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015775
15776 $TestResults .= " <libs>\n";
15777 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15778 {
15779 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15780 $TestResults .= " <name>$Library</name>\n";
15781 }
15782 $TestResults .= " </libs>\n";
15783
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015784 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785 $TestResults .= " <types>".$TotalTypes."</types>\n";
15786
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015787 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15788 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15790
15791 # problem summary
15792 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15793 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15794
15795 $Problem_Summary .= " <problems_with_types>\n";
15796 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15797 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15798 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15799 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15800 $Problem_Summary .= " </problems_with_types>\n";
15801
15802 $Problem_Summary .= " <problems_with_symbols>\n";
15803 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15804 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15805 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015806 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 $Problem_Summary .= " </problems_with_symbols>\n";
15808
15809 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015810 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015811 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015812
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015813 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15814
15815 return ($TestInfo.$TestResults.$Problem_Summary, "");
15816 }
15817 else
15818 { # HTML
15819 # test info
15820 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015821 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015822
15823 if($TargetComponent eq "library") {
15824 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
15825 }
15826 else {
15827 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
15828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015829
15830 my (@VInf1, @VInf2, $AddTestInfo) = ();
15831 if($Arch1 ne "unknown"
15832 and $Arch2 ne "unknown")
15833 { # CPU arch
15834 if($Arch1 eq $Arch2)
15835 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015836 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015837 }
15838 else
15839 { # go to the version number
15840 push(@VInf1, showArch($Arch1));
15841 push(@VInf2, showArch($Arch2));
15842 }
15843 }
15844 if($GccV1 ne "unknown"
15845 and $GccV2 ne "unknown"
15846 and $OStarget ne "windows")
15847 { # GCC version
15848 if($GccV1 eq $GccV2)
15849 { # go to the separate section
15850 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15851 }
15852 else
15853 { # go to the version number
15854 push(@VInf1, "gcc ".$GccV1);
15855 push(@VInf2, "gcc ".$GccV2);
15856 }
15857 }
15858 # show long version names with GCC version and CPU architecture name (if different)
15859 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15860 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15861 $TestInfo .= $AddTestInfo;
15862 #if($COMMON_LANGUAGE{1}) {
15863 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15864 #}
15865 if($ExtendedCheck) {
15866 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15867 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 if($JoinReport)
15869 {
15870 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015871 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015872 }
15873 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015874 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015875 }
15876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877 $TestInfo .= "</table>\n";
15878
15879 # test results
15880 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015883 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015884 {
15885 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15886 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15887 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015888
15889 if(my @Sources = keys(%{$Registered_Sources{1}}))
15890 {
15891 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15892 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015894
15895 if(not $ExtendedCheck)
15896 {
15897 my $Libs_Link = "0";
15898 $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 +040015899 $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 +040015900 }
15901
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015902 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015903
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015904 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015905 if($JoinReport) {
15906 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15907 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015908 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015909 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015910 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15911 }
15912 else {
15913 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15914 }
15915 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015916 $TestResults .= "</table>\n";
15917
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015918 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015919 # problem summary
15920 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015921 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015922 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15923
15924 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015925 if($Added>0)
15926 {
15927 if($JoinReport) {
15928 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15929 }
15930 else {
15931 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15932 }
15933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015934 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015935 $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 +040015936
15937 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 if($Removed>0)
15939 {
15940 if($JoinReport) {
15941 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15942 }
15943 else {
15944 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15945 }
15946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015947 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015948 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15949 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015950
15951 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015952 $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 +040015953 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015954 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15955 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015956
15957 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015958 $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 +040015959 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015960 $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 +040015961
15962 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015963 $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 +040015964 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015965 $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 +040015966
15967 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015968 $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 +040015969 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015970 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15971 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015972
15973 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015974 $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 +040015975 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015976 $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 +040015977
15978 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015979 $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 +040015980 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015981 $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 +040015982
15983 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015984 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15985 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015987 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015988 $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 +040015989
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015990 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015991 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015992 {
15993 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015994 $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 +030015995 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015997
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015998 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015999 {
16000 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016001 $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 +030016002 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016004
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016005 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016006 {
16007 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16008 $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 +030016009 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016010 }
16011
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016012 $META_DATA .= "tool_version:$TOOL_VERSION";
16013 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016014 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16016 }
16017}
16018
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016019sub getStyle($$$)
16020{
16021 my ($Subj, $Act, $Num) = @_;
16022 my %Style = (
16023 "A"=>"new",
16024 "R"=>"failed",
16025 "S"=>"passed",
16026 "L"=>"warning",
16027 "M"=>"failed",
16028 "H"=>"failed"
16029 );
16030 if($Num>0) {
16031 return " class='".$Style{$Act}."'";
16032 }
16033 return "";
16034}
16035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016036sub show_number($)
16037{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016038 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016039 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016040 my $Num = cut_off_number($_[0], 2, 0);
16041 if($Num eq "0")
16042 {
16043 foreach my $P (3 .. 7)
16044 {
16045 $Num = cut_off_number($_[0], $P, 1);
16046 if($Num ne "0") {
16047 last;
16048 }
16049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016050 }
16051 if($Num eq "0") {
16052 $Num = $_[0];
16053 }
16054 return $Num;
16055 }
16056 return $_[0];
16057}
16058
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016059sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016060{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016061 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016062 if($num!~/\./)
16063 {
16064 $num .= ".";
16065 foreach (1 .. $digs_to_cut-1) {
16066 $num .= "0";
16067 }
16068 }
16069 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16070 {
16071 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16072 $num .= "0";
16073 }
16074 }
16075 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16076 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16077 }
16078 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016079 if($z) {
16080 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016082 return $num;
16083}
16084
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016085sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016087 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016088 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016089
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016090 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016091 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16092 {
16093 my $Header = $Constants{1}{$Constant}{"Header"};
16094 if(not $Header)
16095 { # added
16096 $Header = $Constants{2}{$Constant}{"Header"}
16097 }
16098
16099 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16100 {
16101 if(not defined $CompatRules{$Level}{$Kind}) {
16102 next;
16103 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016104 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016105 next;
16106 }
16107 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016109 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016110
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016111 if($ReportFormat eq "xml")
16112 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016113 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016114 {
16115 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016116 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016117 {
16118 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016119 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16120 {
16121 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16122 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16123 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016124
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016125 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16126 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16127 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016128 if($Overcome) {
16129 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16130 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016131 $CHANGED_CONSTANTS .= " </problem>\n";
16132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016133 $CHANGED_CONSTANTS .= " </constant>\n";
16134 }
16135 $CHANGED_CONSTANTS .= " </header>\n";
16136 }
16137 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16138 }
16139 else
16140 { # HTML
16141 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016142 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143 {
16144 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016145 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016147 my $Report = "";
16148
16149 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16150 {
16151 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16152 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016153 $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 +040016154 $Number += 1;
16155 }
16156 if($Report)
16157 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016158 $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 +040016159 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16160 $Report = insertIDs($Report);
16161 }
16162 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016163 }
16164 $CHANGED_CONSTANTS .= "<br/>\n";
16165 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016166 if($CHANGED_CONSTANTS)
16167 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016168 my $Title = "Problems with Constants, $TargetSeverity Severity";
16169 if($TargetSeverity eq "Safe")
16170 { # Safe Changes
16171 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016173 $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 +040016174 }
16175 }
16176 return $CHANGED_CONSTANTS;
16177}
16178
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016179sub getTitle($$$)
16180{
16181 my ($Header, $Library, $NameSpace) = @_;
16182 my $Title = "";
16183 if($Library and $Library!~/\.\w+\Z/) {
16184 $Library .= " (.$LIB_EXT)";
16185 }
16186 if($Header and $Library)
16187 {
16188 $Title .= "<span class='h_name'>$Header</span>";
16189 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16190 }
16191 elsif($Library) {
16192 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16193 }
16194 elsif($Header) {
16195 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16196 }
16197 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016198 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016199 }
16200 return $Title;
16201}
16202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016203sub get_Report_Added($)
16204{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016205 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016206 my $ADDED_INTERFACES = "";
16207 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016208 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016209 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016210 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016211 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016212 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016213 {
16214 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16215 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016216 if($Level eq "Source" and $ReportFormat eq "html")
16217 { # do not show library name in HTML report
16218 $DyLib = "";
16219 }
16220 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016221 }
16222 }
16223 }
16224 if($ReportFormat eq "xml")
16225 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227 {
16228 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230 {
16231 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016232 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016233 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16234 }
16235 $ADDED_INTERFACES .= " </library>\n";
16236 }
16237 $ADDED_INTERFACES .= " </header>\n";
16238 }
16239 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16240 }
16241 else
16242 { # HTML
16243 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016244 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016245 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016246 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016247 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016248 my %NameSpaceSymbols = ();
16249 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016250 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016252 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016253 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016254 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16255 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 foreach my $Interface (@SortedInterfaces)
16257 {
16258 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259 my $Signature = get_Signature($Interface, 2);
16260 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016261 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016262 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016263 if($Interface=~/\A(_Z|\?)/)
16264 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016266 $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 +040016267 }
16268 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016269 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016270 }
16271 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016272 else
16273 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016275 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016276 }
16277 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016278 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 }
16280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016282 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 }
16285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016286 if($ADDED_INTERFACES)
16287 {
16288 my $Anchor = "<a name='Added'></a>";
16289 if($JoinReport) {
16290 $Anchor = "<a name='".$Level."_Added'></a>";
16291 }
16292 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016293 }
16294 }
16295 return $ADDED_INTERFACES;
16296}
16297
16298sub get_Report_Removed($)
16299{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016301 my $REMOVED_INTERFACES = "";
16302 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016303 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016304 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016305 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016307 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016309 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16310 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016311 if($Level eq "Source" and $ReportFormat eq "html")
16312 { # do not show library name in HTML report
16313 $DyLib = "";
16314 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016315 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016316 }
16317 }
16318 }
16319 if($ReportFormat eq "xml")
16320 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016321 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016322 {
16323 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016324 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016325 {
16326 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016327 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16328 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 }
16330 $REMOVED_INTERFACES .= " </library>\n";
16331 }
16332 $REMOVED_INTERFACES .= " </header>\n";
16333 }
16334 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16335 }
16336 else
16337 { # HTML
16338 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016339 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016340 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016341 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016343 my %NameSpaceSymbols = ();
16344 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016345 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016347 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016348 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016349 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16350 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016351 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016352 {
16353 $Removed_Number += 1;
16354 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016355 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016356 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016357 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016358 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016359 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016360 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016362 $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 +040016363 }
16364 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016365 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 }
16367 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016368 else
16369 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016370 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016371 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016372 }
16373 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016374 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 }
16376 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377 }
16378 }
16379 $REMOVED_INTERFACES .= "<br/>\n";
16380 }
16381 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 if($REMOVED_INTERFACES)
16383 {
16384 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16385 if($JoinReport) {
16386 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16387 }
16388 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016389 }
16390 }
16391 return $REMOVED_INTERFACES;
16392}
16393
16394sub getXmlParams($$)
16395{
16396 my ($Content, $Problem) = @_;
16397 return "" if(not $Content or not $Problem);
16398 my %XMLparams = ();
16399 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16400 {
16401 my $Macro = "\@".lc($Attr);
16402 if($Content=~/\Q$Macro\E/) {
16403 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16404 }
16405 }
16406 my @PString = ();
16407 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016408 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016409 }
16410 if(@PString) {
16411 return " ".join(" ", @PString);
16412 }
16413 else {
16414 return "";
16415 }
16416}
16417
16418sub addMarkup($)
16419{
16420 my $Content = $_[0];
16421 # auto-markup
16422 $Content=~s/\n[ ]*//; # spaces
16423 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16424 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016425 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016426 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16427 if($Content=~/\ANOTE:/)
16428 { # notes
16429 $Content=~s!(NOTE):!<b>$1</b>:!g;
16430 }
16431 else {
16432 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16433 }
16434 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16435 my @Keywords = (
16436 "void",
16437 "const",
16438 "static",
16439 "restrict",
16440 "volatile",
16441 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016442 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 );
16444 my $MKeys = join("|", @Keywords);
16445 foreach (@Keywords) {
16446 $MKeys .= "|non-".$_;
16447 }
16448 $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 +040016449
16450 # Markdown
16451 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16452 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 return $Content;
16454}
16455
16456sub applyMacroses($$$$)
16457{
16458 my ($Level, $Kind, $Content, $Problem) = @_;
16459 return "" if(not $Content or not $Problem);
16460 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16461 $Content = addMarkup($Content);
16462 # macros
16463 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16464 {
16465 my $Macro = "\@".lc($Attr);
16466 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016467 if(not defined $Value
16468 or $Value eq "") {
16469 next;
16470 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016471
16472 if(index($Content, $Macro)==-1) {
16473 next;
16474 }
16475
16476 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16477 and $Kind!~/_Type_/
16478 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016481 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016482 $Value = black_name($Value);
16483 }
16484 elsif($Value=~/\s/) {
16485 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16486 }
16487 elsif($Value=~/\A\d+\Z/
16488 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16489 { # bits to bytes
16490 if($Value % $BYTE_SIZE)
16491 { # bits
16492 if($Value==1) {
16493 $Value = "<b>".$Value."</b> bit";
16494 }
16495 else {
16496 $Value = "<b>".$Value."</b> bits";
16497 }
16498 }
16499 else
16500 { # bytes
16501 $Value /= $BYTE_SIZE;
16502 if($Value==1) {
16503 $Value = "<b>".$Value."</b> byte";
16504 }
16505 else {
16506 $Value = "<b>".$Value."</b> bytes";
16507 }
16508 }
16509 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016510 else
16511 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016512 $Value = "<b>".htmlSpecChars($Value)."</b>";
16513 }
16514 $Content=~s/\Q$Macro\E/$Value/g;
16515 }
16516
16517 if($Content=~/(\A|[^\@\w])\@\w/)
16518 {
16519 if(not $IncompleteRules{$Level}{$Kind})
16520 { # only one warning
16521 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16522 $IncompleteRules{$Level}{$Kind} = 1;
16523 }
16524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 return $Content;
16526}
16527
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016528sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016529{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016530 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016531 my $INTERFACE_PROBLEMS = "";
16532 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016533
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016534 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016535 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016536 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16537 if($SV and defined $CompatProblems{$Level}{$SN}) {
16538 next;
16539 }
16540 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 {
16542 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016543 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16546 my $DyLib = $Symbol_Library{1}{$Symbol};
16547 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548 { # Symbol with Version
16549 $DyLib = $Symbol_Library{1}{$VSym};
16550 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016551 if(not $DyLib)
16552 { # const global data
16553 $DyLib = "";
16554 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016555 if($Level eq "Source" and $ReportFormat eq "html")
16556 { # do not show library name in HTML report
16557 $DyLib = "";
16558 }
16559 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16560 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016561 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016562 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16563 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016564 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016565 }
16566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016567 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16568 {
16569 delete($SymbolChanges{$Symbol}{$Kind});
16570 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016572 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016573 }
16574 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 if(not keys(%{$SymbolChanges{$Symbol}})) {
16576 delete($SymbolChanges{$Symbol});
16577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 if($ReportFormat eq "xml")
16581 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016583 {
16584 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 {
16587 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016588 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16589 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 {
16591 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16592 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16593 {
16594 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16595 {
16596 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016597 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016598
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016599 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16600 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16601 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16602 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16603 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016604 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16605 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016607 $INTERFACE_PROBLEMS .= " </problem>\n";
16608 }
16609 }
16610 $INTERFACE_PROBLEMS .= " </symbol>\n";
16611 }
16612 $INTERFACE_PROBLEMS .= " </library>\n";
16613 }
16614 $INTERFACE_PROBLEMS .= " </header>\n";
16615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016616 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 }
16618 else
16619 { # HTML
16620 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016621 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016622 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016623 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016624 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016625 my (%NameSpaceSymbols, %NewSignature) = ();
16626 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016627 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016629 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016631 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016632 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 +040016633 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016635 my $Signature = get_Signature($Symbol, 1);
16636 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016638 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016640 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016642 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016643 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016645 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 }
16647 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16648 {
16649 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016650 $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 +040016651 $ProblemNum += 1;
16652 $ProblemsNum += 1;
16653 }
16654 }
16655 }
16656 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016657 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016658 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016659 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016660 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016661 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016662 }
16663 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016664 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016666 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16667 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16668 if($NewSignature{$Symbol})
16669 { # argument list changed to
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016670 $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 +040016671 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016672 if($Symbol=~/\A(_Z|\?)/) {
16673 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16674 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016675 $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 +040016676 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016678 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 }
16680 }
16681 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016682 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016683 }
16684 }
16685 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016686
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016687 if($INTERFACE_PROBLEMS)
16688 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016689 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16690 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16691 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 { # Safe Changes
16693 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016695 $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 +040016696 }
16697 }
16698 return $INTERFACE_PROBLEMS;
16699}
16700
16701sub get_Report_TypeProblems($$)
16702{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016703 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016704 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016705 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016706
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016707 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016708 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016709 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 {
16711 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16712 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016713 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016715 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016716 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016717 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016718
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016719 if($Severity eq "Safe"
16720 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 next;
16722 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016723
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016724 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16725 {
16726 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16727 { # select a problem with the highest priority
16728 next;
16729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016730 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016731
16732 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016733 }
16734 }
16735 }
16736 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016737
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016738 my %Kinds_Locations = ();
16739 foreach my $TypeName (keys(%TypeChanges))
16740 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016741 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16743 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016744 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016746 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016747 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 { # other priority
16749 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16750 next;
16751 }
16752 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16753 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016754 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016755 { # duplicate target
16756 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16757 next;
16758 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016759 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016760 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016762 }
16763 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16764 delete($TypeChanges{$TypeName}{$Kind});
16765 }
16766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016767 if(not keys(%{$TypeChanges{$TypeName}})) {
16768 delete($TypeChanges{$TypeName});
16769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016770 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016771
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016772 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 +040016773 if($ReportFormat eq "xml")
16774 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016775 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016776 {
16777 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016779 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016780 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016781 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16782 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016783 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 {
16785 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16786 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16787 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16788 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16789 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16790 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016791 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16792 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 $TYPE_PROBLEMS .= " </problem>\n";
16795 }
16796 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016797 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016798 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 $TYPE_PROBLEMS .= showVTables($TypeName);
16800 }
16801 $TYPE_PROBLEMS .= " </type>\n";
16802 }
16803 $TYPE_PROBLEMS .= " </header>\n";
16804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016805 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016806 }
16807 else
16808 { # HTML
16809 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016812 my (%NameSpace_Type) = ();
16813 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016814 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016815 }
16816 foreach my $NameSpace (sort keys(%NameSpace_Type))
16817 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016818 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016819 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 +040016820 foreach my $TypeName (@SortedTypes)
16821 {
16822 my $ProblemNum = 1;
16823 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016824
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016825 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16826 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016827 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 {
16829 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16830 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16831 {
16832 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016833 $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 +040016834 $ProblemNum += 1;
16835 $ProblemsNum += 1;
16836 }
16837 }
16838 }
16839 $ProblemNum -= 1;
16840 if($TYPE_REPORT)
16841 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016842 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016843 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016844 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016845 $ShowVTables = showVTables($TypeName);
16846 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016847
16848 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016849 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16850 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16851 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16852 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016854 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016855 }
16856 }
16857 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016858 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016859 }
16860 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016861
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 if($TYPE_PROBLEMS)
16863 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016864 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16865 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016866 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016867 { # Safe Changes
16868 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016870 $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 +040016871 }
16872 }
16873 return $TYPE_PROBLEMS;
16874}
16875
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016876sub show_Type($$$)
16877{
16878 my ($Name, $Html, $LibVersion) = @_;
16879 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16880 $TType = lc($TType);
16881 if($TType=~/struct|union|enum/) {
16882 $Name=~s/\A\Q$TType\E //g;
16883 }
16884 if($Html) {
16885 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16886 }
16887 else {
16888 $Name = $TType." ".$Name;
16889 }
16890 return $Name;
16891}
16892
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016893sub get_Anchor($$$)
16894{
16895 my ($Kind, $Level, $Severity) = @_;
16896 if($JoinReport)
16897 {
16898 if($Severity eq "Safe") {
16899 return "Other_".$Level."_Changes_In_".$Kind."s";
16900 }
16901 else {
16902 return $Kind."_".$Level."_Problems_".$Severity;
16903 }
16904 }
16905 else
16906 {
16907 if($Severity eq "Safe") {
16908 return "Other_Changes_In_".$Kind."s";
16909 }
16910 else {
16911 return $Kind."_Problems_".$Severity;
16912 }
16913 }
16914}
16915
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016916sub showVTables($)
16917{
16918 my $TypeName = $_[0];
16919 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016920 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016921 if(defined $Type1{"VTable"}
16922 and keys(%{$Type1{"VTable"}}))
16923 {
16924 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016925 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 if(defined $Type2{"VTable"}
16927 and keys(%{$Type2{"VTable"}}))
16928 {
16929 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16930 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016931 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016933 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16934 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 }
16936 my $VTABLES = "";
16937 if($ReportFormat eq "xml")
16938 { # XML
16939 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016940 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016942 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016943 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16944 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 $VTABLES .= " </entry>\n";
16946 }
16947 $VTABLES .= " </vtable>\n\n";
16948 }
16949 else
16950 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016951 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016952 $VTABLES .= "<tr><th>Offset</th>";
16953 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 {
16957 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016958 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016959 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016960 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016962 $Color1 = " class='failed'";
16963 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 }
16965 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016966 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 }
16968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 $VTABLES .= "<tr><th>".$Index."</th>\n";
16970 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16971 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 }
16973 $VTABLES .= "</table><br/>\n";
16974 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016975 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016976 }
16977 return $VTABLES;
16978 }
16979 }
16980 return "";
16981}
16982
16983sub simpleVEntry($)
16984{
16985 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016986 if(not defined $VEntry
16987 or $VEntry eq "") {
16988 return "";
16989 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016990
16991 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016992 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16993 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16994 if($VEntry=~/\A_ZThn.+\Z/) {
16995 $VEntry = "non-virtual thunk";
16996 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016997 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016998 # support for old GCC versions
16999 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17000 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17001 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17003 return $VEntry;
17004}
17005
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017006sub adjustParamPos($$$)
17007{
17008 my ($Pos, $Symbol, $LibVersion) = @_;
17009 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17010 {
17011 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17012 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17013 {
17014 return $Pos-1;
17015 }
17016
17017 return $Pos;
17018 }
17019
17020 return undef;
17021}
17022
17023sub getParamPos($$$)
17024{
17025 my ($Name, $Symbol, $LibVersion) = @_;
17026
17027 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17028 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17029 {
17030 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17031 foreach (keys(%{$Info->{"Param"}}))
17032 {
17033 if($Info->{"Param"}{$_}{"name"} eq $Name)
17034 {
17035 return $_;
17036 }
17037 }
17038 }
17039
17040 return undef;
17041}
17042
17043sub getParamName($)
17044{
17045 my $Loc = $_[0];
17046 $Loc=~s/\->.*//g;
17047 return $Loc;
17048}
17049
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017050sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017051{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017052 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017053 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017054
17055 if(defined $AffectLimit)
17056 {
17057 $LIMIT = $AffectLimit;
17058 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017059
17060 my %SymSel = ();
17061 my %SymLocKind = ();
17062
17063 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017064 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017065 if(index($Symbol, "_Z")==0
17066 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 { # duplicated problems for C2 constructors, D2 and D0 destructors
17068 next;
17069 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017070
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017071 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017073 if(not defined $CompatProblems{$Level}{$Symbol}
17074 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17075 next;
17076 }
17077
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017078 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017079 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017080 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 next;
17082 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017083
17084 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17085 if($Level eq "Source")
17086 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017087 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017088 }
17089
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017090 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017091 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 { # duplicated problems for versioned symbols
17093 next;
17094 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017095
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017096 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017097 if($Type_Name ne $Target_TypeName) {
17098 next;
17099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017100
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017101 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017102 }
17103 }
17104 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017105
17106 foreach my $Symbol (sort keys(%SymLocKind))
17107 {
17108 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17109 {
17110 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17111 {
17112 $SymSel{$Symbol}{"Loc"} = $Loc;
17113 $SymSel{$Symbol}{"Kind"} = $Kind;
17114
17115 last LOOP;
17116 }
17117 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017118 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017119
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017120 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017121 my $Num = 0;
17122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 if($ReportFormat eq "xml")
17124 { # XML
17125 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017126
17127 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017128 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017129 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017130 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017131 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017134 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017135 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017136 $Target .= " param=\"$PName\"";
17137 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017139 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017140 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017142 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017143 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017144 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017145
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017146 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017147 $Target .= " field=\"$1\"";
17148 }
17149
17150 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017151 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017152 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017153
17154 if($Num>$LIMIT) {
17155 last LOOP;
17156 }
17157
17158 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017159 }
17160 $Affected .= " </affected>\n";
17161 }
17162 else
17163 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017164 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017165 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017166 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17167 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017168 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017169 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17170
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017171 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017172 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17173
17174 if($Num>$LIMIT) {
17175 last;
17176 }
17177
17178 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017180
17181 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017182 $Affected .= " ...\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017183 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017184
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017185 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017186 if($Affected)
17187 {
17188 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017189 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 }
17191 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017192
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017193 return $Affected;
17194}
17195
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017196sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017198 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017199 if($L2=~/\A(retval|this)\b/
17200 and $L1!~/\A(retval|this)\b/)
17201 {
17202 if($L1!~/\-\>/) {
17203 return 1;
17204 }
17205 elsif($L2=~/\-\>/) {
17206 return 1;
17207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 }
17209 return 0;
17210}
17211
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017212sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017213{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017214 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017215
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017216 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017217
17218 my $Location_I = $Location;
17219 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017221 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017222
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017223 if($Kind eq "Overridden_Virtual_Method"
17224 or $Kind eq "Overridden_Virtual_Method_B") {
17225 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17226 }
17227 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17228 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017229 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017231 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17232 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017233 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17234 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 if($ClassName eq $Problem{"Type_Name"}) {
17237 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17238 }
17239 else {
17240 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17241 }
17242 }
17243 else
17244 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017245 my $TypeID = undef;
17246
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247 if($Location=~/retval/)
17248 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017249 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017250 push(@Sentence, "Field \'".$Location."\' in return value");
17251 }
17252 else {
17253 push(@Sentence, "Return value");
17254 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017255
17256 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257 }
17258 elsif($Location=~/this/)
17259 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017260 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017261 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17262 }
17263 else {
17264 push(@Sentence, "\'this\' pointer");
17265 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017266
17267 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017268 }
17269 else
17270 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017271
17272 my $PName = getParamName($Location);
17273 my $PPos = getParamPos($PName, $Symbol, 1);
17274
17275 if(index($Location, "->")!=-1) {
17276 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277 }
17278 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017279 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017280 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017281 if($PName) {
17282 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017283 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017284
17285 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17286 }
17287
17288 if($Location!~/this/)
17289 {
17290 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017291 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017292 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017293 push(@Sentence, "(pointer)");
17294 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017295 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017296 push(@Sentence, "(reference)");
17297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017298 }
17299 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017300
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301 if($Location eq "this") {
17302 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17303 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017304 else
17305 {
17306 my $Location_T = $Location;
17307 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17308
17309 my $TypeID_Problem = $TypeID;
17310 if($Location_T) {
17311 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17312 }
17313
17314 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17315 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17316 }
17317 else {
17318 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017320 }
17321 }
17322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017323 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017324 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 +040017325 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017326
17327 my $Sent = join(" ", @Sentence);
17328
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017329 $Sent=~s/->/./g;
17330
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017331 if($ReportFormat eq "xml")
17332 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017333 $Sent=~s/'//g;
17334 }
17335
17336 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017337}
17338
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017339sub getFieldType($$$)
17340{
17341 my ($Location, $TypeId, $LibVersion) = @_;
17342
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017343 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017344
17345 foreach my $Name (@Fields)
17346 {
17347 my %Info = get_BaseType($TypeId, $LibVersion);
17348
17349 foreach my $Pos (keys(%{$Info{"Memb"}}))
17350 {
17351 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17352 {
17353 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17354 last;
17355 }
17356 }
17357 }
17358
17359 return $TypeId;
17360}
17361
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362sub get_XmlSign($$)
17363{
17364 my ($Symbol, $LibVersion) = @_;
17365 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17366 my $Report = "";
17367 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17368 {
17369 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017370 my $Type = $Info->{"Param"}{$Pos}{"type"};
17371 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017372 foreach my $Typedef (keys(%ChangedTypedef))
17373 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017374 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17375 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17376 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017377 }
17378 $Report .= " <param pos=\"$Pos\">\n";
17379 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017380 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017381 $Report .= " </param>\n";
17382 }
17383 if(my $Return = $Info->{"Return"})
17384 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017385 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017386 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017387 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388 $Report .= " </retval>\n";
17389 }
17390 return $Report;
17391}
17392
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017393sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017394{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017395 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017397 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017399 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17400 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 next;
17402 }
17403 $Report .= " <symbol name=\"$Symbol\">\n";
17404 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017405 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017406 {
17407 if(defined $CompleteSignature{1}{$Symbol}
17408 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17409 {
17410 $P1 = get_XmlSign($Symbol, 1);
17411 $S1 = get_Signature($Symbol, 1);
17412 }
17413 elsif($Symbol=~/\A(_Z|\?)/) {
17414 $S1 = $tr_name{$Symbol};
17415 }
17416 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017417 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017418 {
17419 if(defined $CompleteSignature{2}{$Symbol}
17420 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17421 {
17422 $P2 = get_XmlSign($Symbol, 2);
17423 $S2 = get_Signature($Symbol, 2);
17424 }
17425 elsif($Symbol=~/\A(_Z|\?)/) {
17426 $S2 = $tr_name{$Symbol};
17427 }
17428 }
17429 if($S1)
17430 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017431 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 $Report .= $P1;
17433 $Report .= " </old>\n";
17434 }
17435 if($S2 and $S2 ne $S1)
17436 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017437 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017438 $Report .= $P2;
17439 $Report .= " </new>\n";
17440 }
17441 $Report .= " </symbol>\n";
17442 }
17443 $Report .= "</symbols_info>\n";
17444 return $Report;
17445}
17446
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017447sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017449 my ($Level, $Report) = @_;
17450 if($ReportFormat eq "xml") {
17451 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017452 }
17453 if($StdOut)
17454 { # --stdout option
17455 print STDOUT $Report;
17456 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017457 else
17458 {
17459 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017460 mkpath(get_dirname($RPath));
17461
17462 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17463 print REPORT $Report;
17464 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017465 }
17466}
17467
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017468sub getReport($)
17469{
17470 my $Level = $_[0];
17471 if($ReportFormat eq "xml")
17472 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017473 if($Level eq "Join")
17474 {
17475 my $Report = "<reports>\n";
17476 $Report .= getReport("Binary");
17477 $Report .= getReport("Source");
17478 $Report .= "</reports>\n";
17479 return $Report;
17480 }
17481 else
17482 {
17483 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17484 my ($Summary, $MetaData) = get_Summary($Level);
17485 $Report .= $Summary."\n";
17486 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17487 $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 +040017488
17489 # additional symbols info (if needed)
17490 # $Report .= get_Report_SymbolsInfo($Level);
17491
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017492 $Report .= "</report>\n";
17493 return $Report;
17494 }
17495 }
17496 else
17497 { # HTML
17498 my $CssStyles = readModule("Styles", "Report.css");
17499 my $JScripts = readModule("Scripts", "Sections.js");
17500 if($Level eq "Join")
17501 {
17502 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17503 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017504 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017505 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17506 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 +040017507 my ($BSummary, $BMetaData) = get_Summary("Binary");
17508 my ($SSummary, $SMetaData) = get_Summary("Source");
17509 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 +030017510 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017511 <br/>
17512 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017513 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17514 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017515 </div>";
17516 $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>";
17517 $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 +030017518 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017519 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017520 return $Report;
17521 }
17522 else
17523 {
17524 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017525 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17526 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17527 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 +040017528 if($Level eq "Binary")
17529 {
17530 if(getArch(1) eq getArch(2)
17531 and getArch(1) ne "unknown") {
17532 $Description .= " on ".showArch(getArch(1));
17533 }
17534 }
17535 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 +030017536 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017537 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17538 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17539 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017540 $Report .= "</div>\n<br/><br/><br/>\n";
17541 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017542 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017543 return $Report;
17544 }
17545 }
17546}
17547
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017548sub getLegend()
17549{
17550 return "<br/>
17551<table class='summary'>
17552<tr>
17553 <td class='new'>added</td>
17554 <td class='passed'>compatible</td>
17555</tr>
17556<tr>
17557 <td class='warning'>warning</td>
17558 <td class='failed'>incompatible</td>
17559</tr></table>\n";
17560}
17561
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017562sub createReport()
17563{
17564 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017565 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017566 writeReport("Join", getReport("Join"));
17567 }
17568 elsif($DoubleReport)
17569 { # default
17570 writeReport("Binary", getReport("Binary"));
17571 writeReport("Source", getReport("Source"));
17572 }
17573 elsif($BinaryOnly)
17574 { # --binary
17575 writeReport("Binary", getReport("Binary"));
17576 }
17577 elsif($SourceOnly)
17578 { # --source
17579 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017580 }
17581}
17582
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017583sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017585 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017586
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017587 $Footer .= "<hr/>";
17588 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017589 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017590 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017591 $Footer .= "<br/>\n";
17592
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017593 return $Footer;
17594}
17595
17596sub get_Report_Problems($$)
17597{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017598 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017599
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017600 my $Report = get_Report_TypeProblems($Severity, $Level);
17601 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017602 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017603 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017604
17605 if($Severity eq "Low" or $Severity eq "Safe") {
17606 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017607 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017609 if($ReportFormat eq "html")
17610 {
17611 if($Report)
17612 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017613 if($JoinReport)
17614 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017615 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017616 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17617 }
17618 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017619 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017622 else
17623 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017624 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017625 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17626 }
17627 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017628 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017629 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017630 }
17631 }
17632 }
17633 return $Report;
17634}
17635
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017636sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017637{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017638 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17639 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17640 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17641 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017642 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17643 <meta name=\"keywords\" content=\"$Keywords\" />
17644 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017645 <title>
17646 $Title
17647 </title>
17648 <style type=\"text/css\">
17649 $Styles
17650 </style>
17651 <script type=\"text/javascript\" language=\"JavaScript\">
17652 <!--
17653 $Scripts
17654 -->
17655 </script>
17656 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017657}
17658
17659sub insertIDs($)
17660{
17661 my $Text = $_[0];
17662 while($Text=~/CONTENT_ID/)
17663 {
17664 if(int($Content_Counter)%2) {
17665 $ContentID -= 1;
17666 }
17667 $Text=~s/CONTENT_ID/c_$ContentID/;
17668 $ContentID += 1;
17669 $Content_Counter += 1;
17670 }
17671 return $Text;
17672}
17673
17674sub checkPreprocessedUnit($)
17675{
17676 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017677 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017678 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017679 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017680
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017681 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017682 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017683 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017684 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017685 chomp($Line);
17686 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017687 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017688 $CurHeader = path_format($1, $OSgroup);
17689 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017690 $CurClass = "";
17691
17692 if(index($CurHeader, $TMP_DIR)==0) {
17693 next;
17694 }
17695
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017696 if(substr($CurHeaderName, 0, 1) eq "<")
17697 { # <built-in>, <command-line>, etc.
17698 $CurHeaderName = "";
17699 $CurHeader = "";
17700 }
17701
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017702 if($ExtraInfo)
17703 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017704 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017705 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17706 }
17707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017708 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017709 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017710 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017711 if($CurHeaderName)
17712 {
17713 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17714 and not $Registered_Headers{$Version}{$CurHeader})
17715 { # not a target
17716 next;
17717 }
17718 if(not is_target_header($CurHeaderName, 1)
17719 and not is_target_header($CurHeaderName, 2))
17720 { # user-defined header
17721 next;
17722 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017723 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017724 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017725
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017726 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017727 {
17728 my ($Name, $Value) = ($1, $2);
17729 if(not $Constants{$Version}{$Name}{"Access"})
17730 {
17731 $Constants{$Version}{$Name}{"Access"} = "public";
17732 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017733 if($CurHeaderName) {
17734 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17735 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017736 }
17737 }
17738 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17739 $Constants{$Version}{$1}{"Access"} = "private";
17740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017741 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017742 else
17743 {
17744 if(defined $ExtraDump)
17745 {
17746 if($Line=~/(\w+)\s*\(/)
17747 { # functions
17748 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17749 }
17750 #elsif($Line=~/(\w+)\s*;/)
17751 #{ # data
17752 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17753 #}
17754 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17755 $CurClass = $2;
17756 }
17757 }
17758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017759 }
17760 close(PREPROC);
17761 foreach my $Constant (keys(%{$Constants{$Version}}))
17762 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017763 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17764 {
17765 delete($Constants{$Version}{$Constant});
17766 next;
17767 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017768 if(not $ExtraDump and ($Constant=~/_h\Z/i
17769 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017770 { # skip
17771 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017772 }
17773 else {
17774 delete($Constants{$Version}{$Constant}{"Access"});
17775 }
17776 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017777 if($Debug)
17778 {
17779 mkpath($DEBUG_PATH{$Version});
17780 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017782}
17783
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017784sub uncoverConstant($$)
17785{
17786 my ($LibVersion, $Constant) = @_;
17787 return "" if(not $LibVersion or not $Constant);
17788 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17789 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17790 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017792
17793 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017794 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017795 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17796 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017797 {
17798 push(@RecurConstant, $Constant);
17799 my $Uncovered = uncoverConstant($LibVersion, $Value);
17800 if($Uncovered ne "") {
17801 $Value = $Uncovered;
17802 }
17803 pop(@RecurConstant);
17804 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017805
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017806 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017807 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017808 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17809 }
17810 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17811}
17812
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017813sub simpleConstant($$)
17814{
17815 my ($LibVersion, $Value) = @_;
17816 if($Value=~/\W/)
17817 {
17818 my $Value_Copy = $Value;
17819 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17820 {
17821 my $Word = $1;
17822 if($Value!~/$Word\s*\(/)
17823 {
17824 my $Val = uncoverConstant($LibVersion, $Word);
17825 if($Val ne "")
17826 {
17827 $Value=~s/\b$Word\b/$Val/g;
17828 }
17829 }
17830 }
17831 }
17832 return $Value;
17833}
17834
17835sub computeValue($)
17836{
17837 my $Value = $_[0];
17838
17839 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17840 return $1;
17841 }
17842
17843 if($Value=~/\A[\d\-\+()]+\Z/) {
17844 return eval($Value);
17845 }
17846
17847 return $Value;
17848}
17849
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017850my %IgnoreConstant = map {$_=>1} (
17851 "VERSION",
17852 "VERSIONCODE",
17853 "VERNUM",
17854 "VERS_INFO",
17855 "PATCHLEVEL",
17856 "INSTALLPREFIX",
17857 "VBUILD",
17858 "VPATCH",
17859 "VMINOR",
17860 "BUILD_STRING",
17861 "BUILD_TIME",
17862 "PACKAGE_STRING",
17863 "PRODUCTION",
17864 "CONFIGURE_COMMAND",
17865 "INSTALLDIR",
17866 "BINDIR",
17867 "CONFIG_FILE_PATH",
17868 "DATADIR",
17869 "EXTENSION_DIR",
17870 "INCLUDE_PATH",
17871 "LIBDIR",
17872 "LOCALSTATEDIR",
17873 "SBINDIR",
17874 "SYSCONFDIR",
17875 "RELEASE",
17876 "SOURCE_ID",
17877 "SUBMINOR",
17878 "MINOR",
17879 "MINNOR",
17880 "MINORVERSION",
17881 "MAJOR",
17882 "MAJORVERSION",
17883 "MICRO",
17884 "MICROVERSION",
17885 "BINARY_AGE",
17886 "INTERFACE_AGE",
17887 "CORE_ABI",
17888 "PATCH",
17889 "COPYRIGHT",
17890 "TIMESTAMP",
17891 "REVISION",
17892 "PACKAGE_TAG",
17893 "PACKAGEDATE",
17894 "NUMVERSION",
17895 "Release",
17896 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017897);
17898
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017899sub constantFilter($$$)
17900{
17901 my ($Name, $Value, $Level) = @_;
17902
17903 if($Level eq "Binary")
17904 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017905 if($Name=~/_t\Z/)
17906 { # __malloc_ptr_t
17907 return 1;
17908 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017909 foreach (keys(%IgnoreConstant))
17910 {
17911 if($Name=~/(\A|_)$_(_|\Z)/)
17912 { # version
17913 return 1;
17914 }
17915 if(/\A[A-Z].*[a-z]\Z/)
17916 {
17917 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17918 { # version
17919 return 1;
17920 }
17921 }
17922 }
17923 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17924 { # version
17925 return 1;
17926 }
17927 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17928 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17929 return 1;
17930 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017931
17932 if($Value=~/\A["'].*['"]/i)
17933 { # string
17934 return 0;
17935 }
17936
17937 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17938 { # static int gcry_pth_init
17939 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017940 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017941 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017942 return 1;
17943 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017944 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017945 { # foo(p)
17946 return 1;
17947 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017948 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017949 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017950 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017951 return 1;
17952 }
17953 }
17954
17955 return 0;
17956}
17957
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017958sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017959{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017960 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017961 foreach my $Constant (keys(%{$Constants{1}}))
17962 {
17963 if($SkipConstants{1}{$Constant})
17964 { # skipped by the user
17965 next;
17966 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017967
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017968 if(my $Header = $Constants{1}{$Constant}{"Header"})
17969 {
17970 if(not is_target_header($Header, 1)
17971 and not is_target_header($Header, 2))
17972 { # user-defined header
17973 next;
17974 }
17975 }
17976 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017977 next;
17978 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017979
17980 my $Old_Value = uncoverConstant(1, $Constant);
17981
17982 if(constantFilter($Constant, $Old_Value, $Level))
17983 { # separate binary and source problems
17984 next;
17985 }
17986
17987 if(not defined $Constants{2}{$Constant}{"Value"})
17988 { # removed
17989 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17990 "Target"=>$Constant,
17991 "Old_Value"=>$Old_Value );
17992 next;
17993 }
17994
17995 if($Constants{2}{$Constant}{"Value"} eq "")
17996 { # empty value
17997 # TODO: implement a rule
17998 next;
17999 }
18000
18001 my $New_Value = uncoverConstant(2, $Constant);
18002
18003 my $Old_Value_Pure = $Old_Value;
18004 my $New_Value_Pure = $New_Value;
18005
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018006 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18007 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18008 $New_Value_Pure=~s/(\W)\s+/$1/g;
18009 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018011 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018012
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018013 if($New_Value_Pure ne $Old_Value_Pure)
18014 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018015 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18016 { # complex values
18017 next;
18018 }
18019 if(computeValue($Old_Value) eq computeValue($New_Value))
18020 { # expressions
18021 next;
18022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018023 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18024 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18025 next;
18026 }
18027 if($Old_Value eq "0" and $New_Value eq "NULL")
18028 { # 0 => NULL
18029 next;
18030 }
18031 if($Old_Value eq "NULL" and $New_Value eq "0")
18032 { # NULL => 0
18033 next;
18034 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018035 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018036 "Target"=>$Constant,
18037 "Old_Value"=>$Old_Value,
18038 "New_Value"=>$New_Value );
18039 }
18040 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018041
18042 foreach my $Constant (keys(%{$Constants{2}}))
18043 {
18044 if(not defined $Constants{1}{$Constant}{"Value"})
18045 {
18046 if($SkipConstants{2}{$Constant})
18047 { # skipped by the user
18048 next;
18049 }
18050
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018051 if(my $Header = $Constants{2}{$Constant}{"Header"})
18052 {
18053 if(not is_target_header($Header, 1)
18054 and not is_target_header($Header, 2))
18055 { # user-defined header
18056 next;
18057 }
18058 }
18059 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018060 next;
18061 }
18062
18063 my $New_Value = uncoverConstant(2, $Constant);
18064 if(not defined $New_Value or $New_Value eq "") {
18065 next;
18066 }
18067
18068 if(constantFilter($Constant, $New_Value, $Level))
18069 { # separate binary and source problems
18070 next;
18071 }
18072
18073 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18074 "Target"=>$Constant,
18075 "New_Value"=>$New_Value );
18076 }
18077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018078}
18079
18080sub convert_integer($)
18081{
18082 my $Value = $_[0];
18083 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018084 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018085 return hex($Value);
18086 }
18087 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018088 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018089 return oct($Value);
18090 }
18091 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018092 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018093 return oct($Value);
18094 }
18095 else {
18096 return $Value;
18097 }
18098}
18099
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018100sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018101{
18102 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018103 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018104 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018105 {
18106 if($LibVersion==1)
18107 {
18108 printMsg("WARNING", "checking headers only");
18109 $CheckHeadersOnly = 1;
18110 }
18111 else {
18112 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18113 }
18114 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018115
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018116 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018117 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018118 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018119
18120 if($CheckUndefined)
18121 {
18122 my %UndefinedLibs = ();
18123
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018124 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18125
18126 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018127 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018128 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018129 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018130 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018131 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018132 if($Symbol_Library{$LibVersion}{$Symbol}
18133 or $DepSymbol_Library{$LibVersion}{$Symbol})
18134 { # exported by target library
18135 next;
18136 }
18137 if(index($Symbol, '@')!=-1)
18138 { # exported default symbol version (@@)
18139 $Symbol=~s/\@/\@\@/;
18140 if($Symbol_Library{$LibVersion}{$Symbol}
18141 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18142 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018143 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018144 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018145 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18146 $UndefinedLibs{$Path} = 1;
18147 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018148 }
18149 }
18150 }
18151 if($ExtraInfo)
18152 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018153 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018154 {
18155 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018156 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018157 foreach (@Paths)
18158 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018159 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018160 my ($Dir, $Name) = separate_path($_);
18161
18162 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018163 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018164 }
18165
18166 $Name = parse_libname($Name, "name", $OStarget);
18167 $Name=~s/\Alib//;
18168
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018169 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018170 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018171
18172 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18173 {
18174 $LibString = " -L".esc($Dir).$LibString;
18175 }
18176
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018177 writeFile($ExtraInfo."/libs-string", $LibString);
18178 }
18179 }
18180 }
18181
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018182 if($ExtraInfo) {
18183 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18184 }
18185
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018186 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018187 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018188 if($#LibPaths!=-1)
18189 {
18190 if(not keys(%{$Symbol_Library{$LibVersion}}))
18191 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018192 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018193 printMsg("WARNING", "checking headers only");
18194 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018195 }
18196 }
18197 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018198
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018199 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018200 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018201}
18202
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018203my %Prefix_Lib_Map=(
18204 # symbols for autodetecting library dependencies (by prefix)
18205 "pthread_" => ["libpthread"],
18206 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18207 "cairo_" => ["libcairo"],
18208 "gtk_" => ["libgtk-x11-2.0"],
18209 "atk_" => ["libatk-1.0"],
18210 "gdk_" => ["libgdk-x11-2.0"],
18211 "gl" => ["libGL"],
18212 "glu" => ["libGLU"],
18213 "popt" => ["libpopt"],
18214 "Py" => ["libpython"],
18215 "jpeg_" => ["libjpeg"],
18216 "BZ2_" => ["libbz2"],
18217 "Fc" => ["libfontconfig"],
18218 "Xft" => ["libXft"],
18219 "SSL_" => ["libssl"],
18220 "sem_" => ["libpthread"],
18221 "snd_" => ["libasound"],
18222 "art_" => ["libart_lgpl_2"],
18223 "dbus_g" => ["libdbus-glib-1"],
18224 "GOMP_" => ["libgomp"],
18225 "omp_" => ["libgomp"],
18226 "cms" => ["liblcms"]
18227);
18228
18229my %Pattern_Lib_Map=(
18230 "SL[a-z]" => ["libslang"]
18231);
18232
18233my %Symbol_Lib_Map=(
18234 # symbols for autodetecting library dependencies (by name)
18235 "pow" => "libm",
18236 "fmod" => "libm",
18237 "sin" => "libm",
18238 "floor" => "libm",
18239 "cos" => "libm",
18240 "dlopen" => "libdl",
18241 "deflate" => "libz",
18242 "inflate" => "libz",
18243 "move_panel" => "libpanel",
18244 "XOpenDisplay" => "libX11",
18245 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018246 "clock_gettime" => "librt",
18247 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018248);
18249
18250sub find_SymbolLibs($$)
18251{
18252 my ($LibVersion, $Symbol) = @_;
18253
18254 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18255 { # debug symbols
18256 return ();
18257 }
18258
18259 my %Paths = ();
18260
18261 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18262 {
18263 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18264 $Paths{$Path} = 1;
18265 }
18266 }
18267
18268 if(my $SymbolPrefix = getPrefix($Symbol))
18269 {
18270 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18271 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18272 }
18273
18274 if(not keys(%Paths))
18275 {
18276 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18277 {
18278 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18279 {
18280 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18281 $Paths{$Path} = 1;
18282 }
18283 }
18284 }
18285 }
18286
18287 if(not keys(%Paths))
18288 {
18289 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18290 {
18291 if($Symbol=~/\A$Prefix/)
18292 {
18293 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18294 {
18295 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18296 $Paths{$Path} = 1;
18297 }
18298 }
18299 }
18300 }
18301 }
18302
18303 if(not keys(%Paths))
18304 {
18305 if($SymbolPrefix)
18306 { # try to find a library by symbol prefix
18307 if($SymbolPrefix eq "inotify" and
18308 index($Symbol, "\@GLIBC")!=-1)
18309 {
18310 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18311 $Paths{$Path} = 1;
18312 }
18313 }
18314 else
18315 {
18316 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18317 $Paths{$Path} = 1;
18318 }
18319 }
18320 }
18321 }
18322
18323 if(my @Paths = keys(%Paths)) {
18324 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18325 }
18326 }
18327 return keys(%Paths);
18328}
18329
18330sub get_LibPath_Prefix($$)
18331{
18332 my ($LibVersion, $Prefix) = @_;
18333
18334 $Prefix = lc($Prefix);
18335 $Prefix=~s/[_]+\Z//g;
18336
18337 foreach ("-2", "2", "-1", "1", "")
18338 { # libgnome-2.so
18339 # libxml2.so
18340 # libdbus-1.so
18341 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18342 return $Path;
18343 }
18344 }
18345 return "";
18346}
18347
18348sub getPrefix($)
18349{
18350 my $Str = $_[0];
18351 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18352 { # XmuValidArea: Xmu
18353 return $1;
18354 }
18355 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18356 { # snfReadFont: snf
18357 return $1;
18358 }
18359 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18360 { # XRRTimes: XRR
18361 return $1;
18362 }
18363 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18364 { # H5HF_delete: H5
18365 return $1;
18366 }
18367 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18368 { # alarm_event_add: alarm_
18369 return $1;
18370 }
18371 elsif($Str=~/\A(([a-z])\2{1,})/i)
18372 { # ffopen
18373 return $1;
18374 }
18375 return "";
18376}
18377
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018378sub getSymbolSize($$)
18379{ # size from the shared library
18380 my ($Symbol, $LibVersion) = @_;
18381 return 0 if(not $Symbol);
18382 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18383 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18384 {
18385 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18386 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18387 {
18388 if($Size<0) {
18389 return -$Size;
18390 }
18391 }
18392 }
18393 return 0;
18394}
18395
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018396sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018397{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18398 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018399 my ($Name, $Type) = @_;
18400
18401 # single
18402 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018403 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018404 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018405 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018406 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018407
18408 # double
18409 if($Name=~/$DEFAULT_STD_PARMS/)
18410 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018411 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018412 {
18413 my ($ShortName, $FuncParams) = split_Signature($Name);
18414
18415 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18416 {
18417 if(index($FParam, "<")!=-1)
18418 {
18419 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18420 my $FParam_N = canonifyName($FParam, "T");
18421 if($FParam_N ne $FParam) {
18422 $Name=~s/\Q$FParam\E/$FParam_N/g;
18423 }
18424 }
18425 }
18426 }
18427 elsif($Type eq "T")
18428 {
18429 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18430
18431 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018432 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018433 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018434 my $FParam = $TParams[0];
18435 foreach my $Pos (1 .. $#TParams)
18436 {
18437 my $TParam = $TParams[$Pos];
18438 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18439 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18440 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018441 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018442 }
18443 }
18444 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018445 if($Type eq "S") {
18446 return formatName($Name, "S");
18447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018448 return $Name;
18449}
18450
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018451sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018452{
18453 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018454 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018455 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018456 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018457 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018458 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018459 next if($tr_name{$Symbol});
18460 $Symbol=~s/[\@\$]+(.*)\Z//;
18461 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018462 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018463 elsif(index($Symbol, "?")==0)
18464 {
18465 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018466 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018467 }
18468 else
18469 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018470 $tr_name{$Symbol} = $Symbol;
18471 $mangled_name_gcc{$Symbol} = $Symbol;
18472 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018473 }
18474 }
18475 if($#MnglNames1 > -1)
18476 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018477 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018478 foreach my $MnglName (@MnglNames1)
18479 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018480 if(my $Unmangled = pop(@UnmangledNames))
18481 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018482 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018483 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18484 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18485 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018486 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018487 and $tr_name{$MnglName}=~/vtable for (.+)/)
18488 { # bind class name and v-table symbol
18489 my $ClassName = $1;
18490 $ClassVTable{$ClassName} = $MnglName;
18491 $VTableClass{$MnglName} = $ClassName;
18492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018493 }
18494 }
18495 }
18496 if($#MnglNames2 > -1)
18497 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018498 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 foreach my $MnglName (@MnglNames2)
18500 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018501 if(my $Unmangled = pop(@UnmangledNames))
18502 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018503 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018504 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018506 }
18507 }
18508 return \%tr_name;
18509}
18510
18511sub link_symbol($$$)
18512{
18513 my ($Symbol, $RunWith, $Deps) = @_;
18514 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18515 return 1;
18516 }
18517 if($Deps eq "+Deps")
18518 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018519 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018520 return 1;
18521 }
18522 }
18523 return 0;
18524}
18525
18526sub link_symbol_internal($$$)
18527{
18528 my ($Symbol, $RunWith, $Where) = @_;
18529 return 0 if(not $Where or not $Symbol);
18530 if($Where->{$RunWith}{$Symbol})
18531 { # the exact match by symbol name
18532 return 1;
18533 }
18534 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18535 { # indirect symbol version, i.e.
18536 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018537 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018538 if($Where->{$RunWith}{$VSym}) {
18539 return 1;
18540 }
18541 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018542 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018543 if($Sym and $Ver)
18544 { # search for the symbol with the same version
18545 # or without version
18546 if($Where->{$RunWith}{$Sym})
18547 { # old: foo@v|foo@@v
18548 # new: foo
18549 return 1;
18550 }
18551 if($Where->{$RunWith}{$Sym."\@".$Ver})
18552 { # old: foo|foo@@v
18553 # new: foo@v
18554 return 1;
18555 }
18556 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18557 { # old: foo|foo@v
18558 # new: foo@@v
18559 return 1;
18560 }
18561 }
18562 return 0;
18563}
18564
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018565sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018566{
18567 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018568 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018569 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018570 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018571 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018572 my $NM = get_CmdPath("nm");
18573 if(not $NM) {
18574 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018575 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018576 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018577 while(<APP>)
18578 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018579 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018580 push(@Imported, $1);
18581 }
18582 }
18583 close(APP);
18584 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018585 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018586 {
18587 my $DumpBinCmd = get_CmdPath("dumpbin");
18588 if(not $DumpBinCmd) {
18589 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18590 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018591 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018592 while(<APP>)
18593 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018594 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18595 push(@Imported, $1);
18596 }
18597 }
18598 close(APP);
18599 }
18600 else
18601 {
18602 my $ReadelfCmd = get_CmdPath("readelf");
18603 if(not $ReadelfCmd) {
18604 exitStatus("Not_Found", "can't find \"readelf\"");
18605 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018606 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018607 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018608 while(<APP>)
18609 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018610 if(defined $symtab)
18611 { # do nothing with symtab
18612 if(index($_, "'.dynsym'")!=-1)
18613 { # dynamic table
18614 $symtab = undef;
18615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018616 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018617 elsif(index($_, "'.symtab'")!=-1)
18618 { # symbol table
18619 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018620 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018621 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018622 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018623 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18624 if($Ndx eq "UND")
18625 { # only imported symbols
18626 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018627 }
18628 }
18629 }
18630 close(APP);
18631 }
18632 return @Imported;
18633}
18634
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018635my %ELF_BIND = map {$_=>1} (
18636 "WEAK",
18637 "GLOBAL"
18638);
18639
18640my %ELF_TYPE = map {$_=>1} (
18641 "FUNC",
18642 "IFUNC",
18643 "OBJECT",
18644 "COMMON"
18645);
18646
18647my %ELF_VIS = map {$_=>1} (
18648 "DEFAULT",
18649 "PROTECTED"
18650);
18651
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018652sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018653{ # read the line of 'readelf' output corresponding to the symbol
18654 my @Info = split(/\s+/, $_[0]);
18655 # Num: Value Size Type Bind Vis Ndx Name
18656 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018657 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018658 shift(@Info); # spaces
18659 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018660
18661 if($#Info==7)
18662 { # UND SYMBOL (N)
18663 if($Info[7]=~/\(\d+\)/) {
18664 pop(@Info);
18665 }
18666 }
18667
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018668 if($#Info!=6)
18669 { # other lines
18670 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018671 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018672 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018673 return () if(not defined $ELF_BIND{$Info[3]});
18674 return () if(not defined $ELF_VIS{$Info[4]});
18675 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18676 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18677 return ();
18678 }
18679 if($OStarget eq "symbian")
18680 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18681 if(index($Info[6], "_._.absent_export_")!=-1)
18682 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18683 return ();
18684 }
18685 $Info[6]=~s/\@.+//g; # remove version
18686 }
18687 if(index($Info[2], "0x") == 0)
18688 { # size == 0x3d158
18689 $Info[2] = hex($Info[2]);
18690 }
18691 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018692}
18693
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018694sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018695{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018696 my ($LibVersion, $Name) = @_;
18697 return "" if(not $LibVersion or not $Name);
18698 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18699 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018700 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018701 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18702}
18703
18704sub get_LibPath_I($$)
18705{
18706 my ($LibVersion, $Name) = @_;
18707 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018708 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018709 if(-f $Name)
18710 { # absolute path
18711 return $Name;
18712 }
18713 else
18714 { # broken
18715 return "";
18716 }
18717 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018718 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018719 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018720 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018721 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018722 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018723 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018724 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018725 }
18726 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18727 { # ldconfig default paths
18728 return $DefaultPath;
18729 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018730 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018731 { # search in default linker directories
18732 # and then in all system paths
18733 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018734 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018735 }
18736 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018737 if(not defined $Cache{"checkSystemFiles"}) {
18738 checkSystemFiles();
18739 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018740 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18741 return $AllObjects[0];
18742 }
18743 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18744 {
18745 if($ShortName ne $Name)
18746 { # FIXME: check this case
18747 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18748 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018749 }
18750 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018751 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018752 # can't find
18753 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018754}
18755
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018756sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018757{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018758 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18759 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018760
18761 my $Real_Path = realpath($Lib_Path);
18762
18763 if(not $Real_Path)
18764 { # broken link
18765 return ();
18766 }
18767
18768 my $Lib_Name = get_filename($Real_Path);
18769
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018770 if($ExtraInfo)
18771 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018772 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018773 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018774 }
18775
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018776 if($IsNeededLib)
18777 {
18778 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18779 return ();
18780 }
18781 }
18782 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018783 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018785 push(@RecurLib, $Lib_Name);
18786 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018787 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18788
18789 if(not $IsNeededLib)
18790 { # special cases: libstdc++ and libc
18791 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18792 {
18793 if($ShortName eq "libstdc++")
18794 { # libstdc++.so.6
18795 $STDCXX_TESTING = 1;
18796 }
18797 elsif($ShortName eq "libc")
18798 { # libc-2.11.3.so
18799 $GLIBC_TESTING = 1;
18800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018801 }
18802 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018803 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018804 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018805 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018806 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018807 mkpath(get_dirname($DebugPath));
18808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018809 if($OStarget eq "macos")
18810 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018811 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018812 if(not $NM) {
18813 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018814 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018815 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018816 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018817 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018818 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018819 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018820 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018821 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018822 else
18823 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018824 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018826 while(<LIB>)
18827 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018828 if($CheckUndefined)
18829 {
18830 if(not $IsNeededLib)
18831 {
18832 if(/ U _([\w\$]+)\s*\Z/)
18833 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018834 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018835 next;
18836 }
18837 }
18838 }
18839
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018840 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018841 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018842 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018843 if($IsNeededLib)
18844 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018845 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018846 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018847 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18848 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018850 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018851 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018852 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018853 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18854 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018855 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18856 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018857 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018858 setLanguage($LibVersion, "C++");
18859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018861 }
18862 }
18863 }
18864 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018865
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018866 if($Deps)
18867 {
18868 if($LIB_TYPE eq "dynamic")
18869 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018870
18871 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018872 if(not $OtoolCmd) {
18873 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018874 }
18875
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018876 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18877 while(<LIB>)
18878 {
18879 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18880 and $1 ne $Lib_Path) {
18881 $NeededLib{$1} = 1;
18882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018883 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018884 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 }
18887 }
18888 elsif($OStarget eq "windows")
18889 { # Windows *.dll, *.lib
18890 my $DumpBinCmd = get_CmdPath("dumpbin");
18891 if(not $DumpBinCmd) {
18892 exitStatus("Not_Found", "can't find \"dumpbin\"");
18893 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018894 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018895 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018896 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018897 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018898 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018899 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018900 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018901 else
18902 { # write to pipe
18903 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018904 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018905 while(<LIB>)
18906 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18907 # 1198 4AD SetThreadToken (forwarded to ...)
18908 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018909 # 1 0 00005B30 ??0?N = ... (with pdb)
18910 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018911 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018912 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018913 { # dynamic, static and forwarded symbols
18914 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018915 if($IsNeededLib)
18916 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018917 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018918 {
18919 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18920 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018922 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018923 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018924 {
18925 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18926 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018927 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18928 {
18929 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18930 setLanguage($LibVersion, "C++");
18931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018933 }
18934 }
18935 }
18936 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018937
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018938 if($Deps)
18939 {
18940 if($LIB_TYPE eq "dynamic")
18941 { # dependencies
18942 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18943 while(<LIB>)
18944 {
18945 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18946 and $1 ne $Lib_Path) {
18947 $NeededLib{path_format($1, $OSgroup)} = 1;
18948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018949 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018950 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
18953 }
18954 else
18955 { # Unix; *.so, *.a
18956 # Symbian: *.dso, *.lib
18957 my $ReadelfCmd = get_CmdPath("readelf");
18958 if(not $ReadelfCmd) {
18959 exitStatus("Not_Found", "can't find \"readelf\"");
18960 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018961 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018962 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018963 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018964 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018965 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018966 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018967 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018968 else
18969 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018970 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018971 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018972 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018973 while(<LIB>)
18974 {
18975 if($LIB_TYPE eq "dynamic")
18976 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018977 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018978 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018979 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018980 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018981 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018982 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983 # do nothing with symtab
18984 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018985 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018986 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018987 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018988 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018989 next;
18990 }
18991 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018992 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018993 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018994 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018995 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018996 if($CheckUndefined)
18997 {
18998 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018999 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019000 }
19001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019002 next;
19003 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019004 if($Bind eq "WEAK")
19005 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019006 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019007 if($Weak eq "-Weak")
19008 { # skip WEAK symbols
19009 next;
19010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019011 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019012 my $Short = $Symbol;
19013 $Short=~s/\@.+//g;
19014 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019015 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019016 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19017 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019018 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019019 if($IsNeededLib)
19020 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019021 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019022 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019023 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19024 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019027 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019028 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019029 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19030 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19031 if($Vers)
19032 {
19033 if($LIB_EXT eq "so")
19034 { # value
19035 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19036 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19037 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019038 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019039 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19040 {
19041 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19042 setLanguage($LibVersion, "C++");
19043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045 }
19046 }
19047 }
19048 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019049
19050 if($Deps and $LIB_TYPE eq "dynamic")
19051 { # dynamic library specifics
19052 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19053 open(LIB, $Cmd." |");
19054
19055 while(<LIB>)
19056 {
19057 if(/NEEDED.+\[([^\[\]]+)\]/)
19058 { # dependencies:
19059 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19060 $NeededLib{$1} = 1;
19061 }
19062 }
19063
19064 close(LIB);
19065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019066 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019067 if($Vers)
19068 {
19069 if(not $IsNeededLib and $LIB_EXT eq "so")
19070 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019071 my %Found = ();
19072
19073 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019074 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019075 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019076 next if(index($Symbol,"\@")==-1);
19077 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019078 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019079 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019080 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019081 if($Symbol_SameValue ne $Symbol
19082 and index($Symbol_SameValue,"\@")==-1)
19083 {
19084 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019085 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019086 last;
19087 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019088 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019089 }
19090 }
19091
19092 # default
19093 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19094 {
19095 next if(defined $Found{$Symbol});
19096 next if(index($Symbol,"\@\@")==-1);
19097
19098 if($Symbol=~/\A([^\@]*)\@\@/
19099 and not $SymVer{$LibVersion}{$1})
19100 {
19101 $SymVer{$LibVersion}{$1} = $Symbol;
19102 $Found{$Symbol} = 1;
19103 }
19104 }
19105
19106 # non-default
19107 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19108 {
19109 next if(defined $Found{$Symbol});
19110 next if(index($Symbol,"\@")==-1);
19111
19112 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19113 and not $SymVer{$LibVersion}{$1})
19114 {
19115 $SymVer{$LibVersion}{$1} = $Symbol;
19116 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019117 }
19118 }
19119 }
19120 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019121 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019122 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019123 foreach my $DyLib (sort keys(%NeededLib))
19124 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019125 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19126
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019127 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19128 {
19129 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19130 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019133 }
19134 }
19135 pop(@RecurLib);
19136 return $Library_Symbol{$LibVersion};
19137}
19138
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019139sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019140{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019141 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019142 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019143 return keys(%Prefixes);
19144}
19145
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019146sub get_prefixes_I($$)
19147{
19148 foreach my $P (@{$_[0]})
19149 {
19150 my @Parts = reverse(split(/[\/\\]+/, $P));
19151 my $Name = $Parts[0];
19152 foreach (1 .. $#Parts)
19153 {
19154 $_[1]->{$Name}{$P} = 1;
19155 last if($_>4 or $Parts[$_] eq "include");
19156 $Name = $Parts[$_].$SLASH.$Name;
19157 }
19158 }
19159}
19160
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019161sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019162{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019163 $Cache{"checkSystemFiles"} = 1;
19164
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019166
19167 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168 {
19169 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019170
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019171 my @Files = cmd_find($DevelPath,"f");
19172 foreach my $Link (cmd_find($DevelPath,"l"))
19173 { # add symbolic links
19174 if(-f $Link) {
19175 push(@Files, $Link);
19176 }
19177 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019178
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019179 # search for headers in /usr/lib
19180 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19181 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19182 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019183
19184 # search for libraries in /usr/lib (including symbolic links)
19185 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19186 foreach my $Path (@Libs)
19187 {
19188 my $N = get_filename($Path);
19189 $SystemObjects{$N}{$Path} = 1;
19190 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019191 }
19192 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019193
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019194 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019195 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019196 next if(not -d $DevelPath);
19197 # search for all header files in the /usr/include
19198 # with or without extension (ncurses.h, QtCore, ...)
19199 push(@SysHeaders, cmd_find($DevelPath,"f"));
19200 foreach my $Link (cmd_find($DevelPath,"l"))
19201 { # add symbolic links
19202 if(-f $Link) {
19203 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019205 }
19206 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019207 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019208}
19209
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019210sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211{
19212 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019213 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19215 {
19216 if(not -e $Dest) {
19217 exitStatus("Access_Error", "can't access \'$Dest\'");
19218 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019219 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019220 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19221 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019222 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019223 }
19224 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019225 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226}
19227
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019228sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019229{
19230 my ($Path, $LibVersion) = @_;
19231 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019232 my $Name = get_filename($Path);
19233 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234 return 1;
19235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019236 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019237 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19238 return 1;
19239 }
19240 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19241 {
19242 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19243 return 1;
19244 }
19245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019246 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019247 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019248 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019249 return 1;
19250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019251 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019252 return 1;
19253 }
19254 }
19255 return 0;
19256}
19257
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019258sub specificHeader($$)
19259{
19260 my ($Header, $Spec) = @_;
19261 my $Name = get_filename($Header);
19262
19263 if($Spec eq "windows")
19264 {# MS Windows
19265 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19266 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19267 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19268 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19269 my @Dirs = (
19270 "win32",
19271 "win64",
19272 "win",
19273 "windows",
19274 "msvcrt"
19275 ); # /gsf-win32/
19276 if(my $DIRs = join("|", @Dirs)) {
19277 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19278 }
19279 }
19280 elsif($Spec eq "macos")
19281 { # Mac OS
19282 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19283 }
19284
19285 return 0;
19286}
19287
19288sub skipAlienHeader($)
19289{
19290 my $Path = $_[0];
19291 my $Name = get_filename($Path);
19292 my $Dir = get_dirname($Path);
19293
19294 if($Tolerance=~/2/)
19295 { # 2 - skip internal headers
19296 my @Terms = (
19297 "p",
19298 "priv",
19299 "int",
19300 "impl",
19301 "implementation",
19302 "internal",
19303 "private",
19304 "old",
19305 "compat",
19306 "debug",
19307 "test",
19308 "gen"
19309 );
19310
19311 my @Dirs = (
19312 "private",
19313 "priv",
19314 "port",
19315 "impl",
19316 "internal",
19317 "detail",
19318 "details",
19319 "old",
19320 "compat",
19321 "debug",
19322 "config",
19323 "compiler",
19324 "platform",
19325 "test"
19326 );
19327
19328 if(my $TERMs = join("|", @Terms)) {
19329 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19330 }
19331 if(my $DIRs = join("|", @Dirs)) {
19332 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19333 }
19334
19335 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19336 }
19337
19338 if($Tolerance=~/1/)
19339 { # 1 - skip non-Linux headers
19340 if($OSgroup ne "windows")
19341 {
19342 if(specificHeader($Path, "windows")) {
19343 return 1;
19344 }
19345 }
19346 if($OSgroup ne "macos")
19347 {
19348 if(specificHeader($Path, "macos")) {
19349 return 1;
19350 }
19351 }
19352 }
19353
19354 # valid
19355 return 0;
19356}
19357
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019358sub skipHeader($$)
19359{
19360 my ($Path, $LibVersion) = @_;
19361 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019362 if(defined $Cache{"skipHeader"}{$Path}) {
19363 return $Cache{"skipHeader"}{$Path};
19364 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019365 if(defined $Tolerance and $Tolerance=~/1|2/)
19366 { # --tolerant
19367 if(skipAlienHeader($Path)) {
19368 return ($Cache{"skipHeader"}{$Path} = 1);
19369 }
19370 }
19371 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19372 return 0;
19373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019374 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19375}
19376
19377sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019378{ # returns:
19379 # 1 - if header should NOT be included and checked
19380 # 2 - if header should NOT be included, but should be checked
19381 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019382 my $Name = get_filename($Path);
19383 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019384 return $Kind;
19385 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019386 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19387 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019388 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019389 if(index($Path, $D)!=-1)
19390 {
19391 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19392 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19393 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019394 }
19395 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019396 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19397 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019399 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19400 {
19401 if($Name=~/$P/) {
19402 return $Kind;
19403 }
19404 if($P=~/[\/\\]/ and $Path=~/$P/) {
19405 return $Kind;
19406 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019407 }
19408 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019410 return 0;
19411}
19412
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019413sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019414{
19415 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019416 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417 { # system directory
19418 return;
19419 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019420 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019421 { # already registered
19422 return;
19423 }
19424 foreach my $Path (find_libs($Dir,"",1))
19425 {
19426 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019427 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019428 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019430 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19431}
19432
19433sub registerObject($$)
19434{
19435 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019436
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019437 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019438 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019439 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019440 {
19441 if(my $SONAME = getSONAME($Path)) {
19442 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19443 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019444 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019445 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19446 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019447 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019448
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019449 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019450 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019451 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019452 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019453 if($ObjArch ne getArch_GCC($LibVersion))
19454 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19455 $CheckedArch{$LibVersion} = 1;
19456 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 +040019457 }
19458 }
19459 }
19460}
19461
19462sub getArch_Object($)
19463{
19464 my $Path = $_[0];
19465
19466 my %MachineType = (
19467 "14C" => "x86",
19468 "8664" => "x86_64",
19469 "1C0" => "arm",
19470 "200" => "ia64"
19471 );
19472
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019473 my %ArchName = (
19474 "s390:31-bit" => "s390",
19475 "s390:64-bit" => "s390x",
19476 "powerpc:common" => "ppc32",
19477 "powerpc:common64" => "ppc64",
19478 "i386:x86-64" => "x86_64",
19479 "mips:3000" => "mips",
19480 "sparc:v8plus" => "sparcv9"
19481 );
19482
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019483 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019484 {
19485 my $DumpbinCmd = get_CmdPath("dumpbin");
19486 if(not $DumpbinCmd) {
19487 exitStatus("Not_Found", "can't find \"dumpbin\"");
19488 }
19489
19490 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19491 my $Out = `$Cmd`;
19492
19493 if($Out=~/(\w+)\smachine/)
19494 {
19495 if(my $Type = $MachineType{uc($1)})
19496 {
19497 return $Type;
19498 }
19499 }
19500 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019501 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019502 {
19503 my $ObjdumpCmd = get_CmdPath("objdump");
19504 if(not $ObjdumpCmd) {
19505 exitStatus("Not_Found", "can't find \"objdump\"");
19506 }
19507
19508 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019509
19510 if($OSgroup eq "windows") {
19511 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19512 }
19513 else {
19514 $Cmd = "LANG=$LOCALE ".$Cmd;
19515 }
19516 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019517
19518 if($Out=~/architecture:\s+([\w\-\:]+)/)
19519 {
19520 my $Arch = $1;
19521 if($Arch=~s/\:(.+)//)
19522 {
19523 my $Suffix = $1;
19524
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019525 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019526 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019527 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019528 }
19529 }
19530
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019531 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019532 $Arch = "x86";
19533 }
19534
19535 if($Arch eq "x86-64") {
19536 $Arch = "x86_64";
19537 }
19538
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019539 if($Arch eq "ia64-elf64") {
19540 $Arch = "ia64";
19541 }
19542
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019543 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019544 }
19545 }
19546 else
19547 { # macos, etc.
19548 # TODO
19549 }
19550
19551 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019552}
19553
19554sub getSONAME($)
19555{
19556 my $Path = $_[0];
19557 return if(not $Path);
19558 if(defined $Cache{"getSONAME"}{$Path}) {
19559 return $Cache{"getSONAME"}{$Path};
19560 }
19561 my $ObjdumpCmd = get_CmdPath("objdump");
19562 if(not $ObjdumpCmd) {
19563 exitStatus("Not_Found", "can't find \"objdump\"");
19564 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019565 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019566 if($OSgroup eq "windows") {
19567 $SonameCmd .= " | find \"SONAME\"";
19568 }
19569 else {
19570 $SonameCmd .= " | grep SONAME";
19571 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019572 if(my $SonameInfo = `$SonameCmd`)
19573 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019574 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19575 return ($Cache{"getSONAME"}{$Path} = $1);
19576 }
19577 }
19578 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019579}
19580
19581sub getSOPaths_Dest($$)
19582{
19583 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019584 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019585 return ();
19586 }
19587 if(-f $Dest)
19588 {
19589 if(not parse_libname($Dest, "name", $OStarget)) {
19590 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19591 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019592 registerObject($Dest, $LibVersion);
19593 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019594 return ($Dest);
19595 }
19596 elsif(-d $Dest)
19597 {
19598 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019599 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019600 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019601 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19602 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019603 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019604 { # all files and symlinks that match the name of a library
19605 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19606 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019607 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019608 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019609 }
19610 }
19611 }
19612 else
19613 { # search for all files and symlinks
19614 foreach my $Path (find_libs($Dest,"",""))
19615 {
19616 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019617 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019618 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019619 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019620 }
19621 if($OSgroup eq "macos")
19622 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019623 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019624 {
19625 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019626 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019627 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019628 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19629 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019630 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019631 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019632 }
19633 }
19634 }
19635 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019636 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637 }
19638 else {
19639 return ();
19640 }
19641}
19642
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019643sub isCyclical($$)
19644{
19645 my ($Stack, $Value) = @_;
19646 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647}
19648
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019649sub getGCC_Opts($)
19650{ # to use in module
19651 my $LibVersion = $_[0];
19652
19653 my @Opts = ();
19654
19655 if($CompilerOptions{$LibVersion})
19656 { # user-defined options
19657 push(@Opts, $CompilerOptions{$LibVersion});
19658 }
19659 if($GccOptions)
19660 { # additional
19661 push(@Opts, $GccOptions);
19662 }
19663
19664 if(@Opts) {
19665 return join(" ", @Opts);
19666 }
19667
19668 return undef;
19669}
19670
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019671sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019672{
19673 my $LibVersion = $_[0];
19674
19675 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19676 return $Cache{"getArch_GCC"}{$LibVersion};
19677 }
19678
19679 my $Arch = undef;
19680
19681 if($GCC_PATH)
19682 {
19683 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19684
19685 my $Cmd = $GCC_PATH." test.c -o test";
19686 if(my $Opts = getGCC_Opts($LibVersion))
19687 { # user-defined options
19688 $Cmd .= " ".$Opts;
19689 }
19690
19691 chdir($TMP_DIR);
19692 system($Cmd);
19693 chdir($ORIG_DIR);
19694
19695 $Arch = getArch_Object("$TMP_DIR/test");
19696
19697 unlink("$TMP_DIR/test.c");
19698 unlink("$TMP_DIR/test");
19699 }
19700
19701 if(not $Arch) {
19702 exitStatus("Error", "can't check ARCH type");
19703 }
19704
19705 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19706}
19707
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019708sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019709{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019710 my $LibVersion = $_[0];
19711
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019712 my $Size = undef;
19713
19714 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019715 if(my $Arch = getArch($LibVersion))
19716 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019717 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019718 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019719 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019720 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19721 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019722 }
19723 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019724
19725 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019726 {
19727 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019728
19729 my $Cmd = $GCC_PATH." -E -dD empty.h";
19730 if(my $Opts = getGCC_Opts($LibVersion))
19731 { # user-defined options
19732 $Cmd .= " ".$Opts;
19733 }
19734
19735 chdir($TMP_DIR);
19736 my $Defines = `$Cmd`;
19737 chdir($ORIG_DIR);
19738
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019739 unlink("$TMP_DIR/empty.h");
19740
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019741 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19742 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019743 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019744 }
19745 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19746 { # GCC 3
19747 my $PTRDIFF = $1;
19748 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019749 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019750 }
19751 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019752 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019753 }
19754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019755 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019756
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019757 if(not $Size) {
19758 exitStatus("Error", "can't check WORD size");
19759 }
19760
19761 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019762}
19763
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019764sub getWordSize($)
19765{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019766 return $WORD_SIZE{$_[0]};
19767}
19768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019769sub majorVersion($)
19770{
19771 my $V = $_[0];
19772 return 0 if(not $V);
19773 my @VParts = split(/\./, $V);
19774 return $VParts[0];
19775}
19776
19777sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019778{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019779 my ($V1, $V2) = @_;
19780 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019781 my @V1Parts = split(/\./, $V1);
19782 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019783 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19784 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019785 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19786 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19787 }
19788 return -1 if($#V1Parts < $#V2Parts);
19789 return 1 if($#V1Parts > $#V2Parts);
19790 return 0;
19791}
19792
19793sub read_ABI_Dump($$)
19794{
19795 my ($LibVersion, $Path) = @_;
19796 return if(not $LibVersion or not -e $Path);
19797 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019798 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799 { # input *.abi
19800 $FilePath = $Path;
19801 }
19802 else
19803 { # input *.abi.tar.gz
19804 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019805 if(not isDump_U($FilePath)) {
19806 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019809
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019810 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019811
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019812 my $Line = readLineNum($FilePath, 0);
19813 if($Line=~/xml/)
19814 { # XML format
19815 loadModule("XmlDump");
19816 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019817 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019818 else
19819 { # Perl Data::Dumper format (default)
19820 open(DUMP, $FilePath);
19821 local $/ = undef;
19822 my $Content = <DUMP>;
19823 close(DUMP);
19824
19825 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19826 { # remove temp file
19827 unlink($FilePath);
19828 }
19829 if($Content!~/};\s*\Z/) {
19830 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19831 }
19832 $ABI = eval($Content);
19833 if(not $ABI) {
19834 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019836 }
19837 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019838 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019839 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019840 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019841 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019842 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019843 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019844 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019845 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019846
19847 if($ABI->{"ABI_DUMP_VERSION"})
19848 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019849 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019851 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019852 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019853 }
19854 else
19855 { # support for old ABI dumps
19856 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019857 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019858 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019859 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019860 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019861
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019862 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019863 {
19864 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 +040019865 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019866
19867 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19868 { # DWARF ABI Dump
19869 $UseConv_Real{$LibVersion}{"P"} = 1;
19870 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19871
19872 $UsedDump{$LibVersion}{"DWARF"} = 1;
19873
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030019874 if(not $TargetComponent_Opt)
19875 {
19876 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
19877 $TargetComponent = "module";
19878 }
19879 else {
19880 $TargetComponent = "object";
19881 }
19882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019883 }
19884
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019885 if(not checkDump($LibVersion, "2.11"))
19886 { # old ABI dumps
19887 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019888 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019889 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019890 { # ABI dump created with --binary option
19891 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19892 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019893 else
19894 { # default
19895 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19896 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019897
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019898 if(defined $ABI->{"Mode"}
19899 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019900 { # --ext option
19901 $ExtendedCheck = 1;
19902 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019903 if($ABI->{"Extra"}) {
19904 $ExtraDump = 1;
19905 }
19906
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019907 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019908 {
19909 $UsedDump{$LibVersion}{"L"} = $Lang;
19910 setLanguage($LibVersion, $Lang);
19911 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019912 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019913 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019914 }
19915 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019916 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019917 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019918 if(not $TInfo)
19919 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019920 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019921 }
19922 my %Tid_TDid = ();
19923 foreach my $TDid (keys(%{$TInfo}))
19924 {
19925 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19926 {
19927 $MAX_ID = $Tid if($Tid>$MAX_ID);
19928 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019929 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019930 }
19931 }
19932 my %NewID = ();
19933 foreach my $Tid (keys(%Tid_TDid))
19934 {
19935 my @TDids = keys(%{$Tid_TDid{$Tid}});
19936 if($#TDids>=1)
19937 {
19938 foreach my $TDid (@TDids)
19939 {
19940 if($TDid) {
19941 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19942 }
19943 else
19944 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019945 my $ID = ++$MAX_ID;
19946
19947 $NewID{$TDid}{$Tid} = $ID;
19948 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19949 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019950 }
19951 }
19952 }
19953 else
19954 {
19955 my $TDid = $TDids[0];
19956 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19957 }
19958 }
19959 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19960 {
19961 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19962 if(defined $Info{"BaseType"})
19963 {
19964 my $Bid = $Info{"BaseType"}{"Tid"};
19965 my $BDid = $Info{"BaseType"}{"TDid"};
19966 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019967 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019968 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19969 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19970 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019971 }
19972 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019974 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019975 read_Machine_DumpInfo($ABI, $LibVersion);
19976 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 if(not $SymbolInfo{$LibVersion})
19978 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019979 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019980 }
19981 if(not keys(%{$SymbolInfo{$LibVersion}}))
19982 { # validation of old-version dumps
19983 if(not $ExtendedCheck) {
19984 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19985 }
19986 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019987 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019988 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019990 else
19991 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019992 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019993 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019994 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019995 }
19996 if(not $DepSymbols)
19997 { # Cannot reconstruct DepSymbols. This may result in false
19998 # positives if the old dump is for library 2. Not a problem if
19999 # old dumps are only from old libraries.
20000 $DepSymbols = {};
20001 }
20002 foreach my $Symbol (keys(%{$DepSymbols})) {
20003 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020005 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020006 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020007
20008 if(my $V = $TargetVersion{$LibVersion}) {
20009 $Descriptor{$LibVersion}{"Version"} = $V;
20010 }
20011 else {
20012 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20013 }
20014
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020015 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020016 if(not $SkipTypes{$LibVersion})
20017 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020018 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020020
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020021 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020022 { # if not defined by -skip-symbols option
20023 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20024 if(not $SkipSymbols{$LibVersion})
20025 { # support for old dumps
20026 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20027 }
20028 if(not $SkipSymbols{$LibVersion})
20029 { # support for old dumps
20030 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20031 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020032 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020033 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020034
20035 if(not $TargetHeaders{$LibVersion})
20036 { # if not defined by -headers-list option
20037 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20038 }
20039
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020040 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020041 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020042 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020043 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020044 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020045 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020046 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020047 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020048 if(not checkDump($LibVersion, "2.10.1")
20049 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020050 { # support for old ABI dumps: added target headers
20051 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020052 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020053 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020054 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020055 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020057 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020058 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020059 if(defined $ABI->{"GccConstants"})
20060 { # 3.0
20061 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20062 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20063 }
20064 }
20065
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020066 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020067 if(not $NestedNameSpaces{$LibVersion})
20068 { # support for old dumps
20069 # Cannot reconstruct NameSpaces. This may affect design
20070 # of the compatibility report.
20071 $NestedNameSpaces{$LibVersion} = {};
20072 }
20073 # target system type
20074 # needed to adopt HTML report
20075 if(not $DumpSystem)
20076 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020077 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020078 }
20079 # recreate environment
20080 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20081 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020082 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020084 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20085 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020086 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020087 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020088 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020089 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20090 {
20091 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20092 setLanguage($LibVersion, "C++");
20093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020094 }
20095 }
20096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020097 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20098 {
20099 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20100 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20101 }
20102 }
20103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020104 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020105 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020106 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020107 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020108 {
20109 if(not $Symbol_Library{$LibVersion}{$MnglName}
20110 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20111 push(@VFunc, $MnglName);
20112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 }
20114 }
20115 translateSymbols(@VFunc, $LibVersion);
20116 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020117 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20118
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020119 if(not checkDump($LibVersion, "3.0"))
20120 { # support for old ABI dumps
20121 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20122 {
20123 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20124 {
20125 if(ref($BaseType) eq "HASH") {
20126 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20127 }
20128 }
20129 }
20130 }
20131
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020132 if(not checkDump($LibVersion, "3.2"))
20133 { # support for old ABI dumps
20134 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20135 {
20136 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20137 {
20138 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20139 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20140 }
20141 }
20142 }
20143
20144 # repair target headers list
20145 delete($TargetHeaders{$LibVersion});
20146 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020147 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20148 }
20149 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20150 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020151 }
20152
20153 # non-target constants from anon enums
20154 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20155 {
20156 if(not $ExtraDump
20157 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20158 {
20159 delete($Constants{$LibVersion}{$Name});
20160 }
20161 }
20162 }
20163
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020164 if(not checkDump($LibVersion, "2.20"))
20165 { # support for old ABI dumps
20166 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20167 {
20168 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20169
20170 if($TType=~/Struct|Union|Enum|Typedef/)
20171 { # repair complex types first
20172 next;
20173 }
20174
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020175 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020176 {
20177 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20178 if($BType=~/Struct|Union|Enum/i)
20179 {
20180 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20181 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20182 }
20183 }
20184 }
20185 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20186 {
20187 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20188 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20189 if($TType=~/Struct|Union|Enum/) {
20190 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20191 }
20192 }
20193 }
20194
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020195 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020196 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020197 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20198 { # support for old ABI dumps < 2.0 (ACC 1.22)
20199 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20200 {
20201 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20202 {
20203 if($Access ne "public") {
20204 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20205 }
20206 }
20207 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20208 }
20209 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20210 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020211 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20212 { # support for old ABI dumps
20213 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20214 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020215 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20216 { # DWARF ABI Dumps
20217 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20218 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020219 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20220 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020222 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20223 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020224 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020225 foreach (keys(%{$TInfo{"Base"}})) {
20226 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020228 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020229 if($TInfo{"Type"} eq "MethodPtr")
20230 {
20231 if(defined $TInfo{"Param"})
20232 { # support for old ABI dumps <= 1.17
20233 if(not defined $TInfo{"Param"}{"0"})
20234 {
20235 my $Max = keys(%{$TInfo{"Param"}});
20236 foreach my $Pos (1 .. $Max) {
20237 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20238 }
20239 delete($TInfo{"Param"}{$Max});
20240 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20241 }
20242 }
20243 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020244 if($TInfo{"BaseType"} eq $TypeId)
20245 { # fix ABI dump
20246 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20247 }
20248 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020249 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020250 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020251 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020252 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20253 if(not $BName)
20254 { # broken type
20255 next;
20256 }
20257 if($TInfo{"Name"} eq $BName)
20258 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020259 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020260 next;
20261 }
20262 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20263 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020264 }
20265 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020266 }
20267 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20268 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020269 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020270 }
20271 }
20272
20273 if(not checkDump($LibVersion, "2.15"))
20274 { # support for old ABI dumps
20275 my %Dups = ();
20276 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20277 {
20278 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020280 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20281 { # remove template decls
20282 delete($SymbolInfo{$LibVersion}{$InfoId});
20283 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020285 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020286 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20287 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020288 { # templates
20289 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020290 }
20291 }
20292 }
20293
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020294 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20295 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020296 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20297 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20298 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20299 { # support for old ABI dumps (< 3.1)
20300 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20301 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20302 { # add "this" first parameter
20303 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20304 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20305
20306 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20307 {
20308 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20309 foreach my $Pos (reverse(0 .. $#Pos)) {
20310 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20311 }
20312 }
20313 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20314 }
20315 }
20316
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020317 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20318 { # ABI dumps have no mangled names for C-functions
20319 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20320 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020321 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20322 { # support for old ABI dumps
20323 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20324 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020325 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20326 { # DWARF ABI Dumps
20327 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20328 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020329 }
20330
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020331 $Descriptor{$LibVersion}{"Dump"} = 1;
20332}
20333
20334sub read_Machine_DumpInfo($$)
20335{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020336 my ($ABI, $LibVersion) = @_;
20337 if($ABI->{"Arch"}) {
20338 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020339 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020340 if($ABI->{"WordSize"}) {
20341 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020342 }
20343 else
20344 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020345 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346 }
20347 if(not $WORD_SIZE{$LibVersion})
20348 { # support for old dumps (<1.23)
20349 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20350 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020351 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020352 }
20353 else
20354 {
20355 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020356 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020358 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20359 { # any "pointer"-type
20360 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020361 last;
20362 }
20363 }
20364 if($PSize)
20365 { # a pointer type size
20366 $WORD_SIZE{$LibVersion} = $PSize;
20367 }
20368 else {
20369 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20370 }
20371 }
20372 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020373 if($ABI->{"GccVersion"}) {
20374 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020375 }
20376}
20377
20378sub read_Libs_DumpInfo($$)
20379{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020380 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020381 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20382 if(not $Library_Symbol{$LibVersion})
20383 { # support for old dumps
20384 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020386 if(keys(%{$Library_Symbol{$LibVersion}})
20387 and not $DumpAPI) {
20388 $Descriptor{$LibVersion}{"Libs"} = "OK";
20389 }
20390}
20391
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020392sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020394 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020395
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020396 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020397 and not $DumpAPI) {
20398 $Descriptor{$LibVersion}{"Headers"} = "OK";
20399 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020400 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020401 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020402 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020403 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020404 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020405
20406 if(keys(%{$ABI->{"Sources"}})
20407 and not $DumpAPI) {
20408 $Descriptor{$LibVersion}{"Sources"} = "OK";
20409 }
20410 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020411 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020412 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20413 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020415}
20416
20417sub find_libs($$$)
20418{
20419 my ($Path, $Type, $MaxDepth) = @_;
20420 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020421 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020422}
20423
20424sub createDescriptor($$)
20425{
20426 my ($LibVersion, $Path) = @_;
20427 if(not $LibVersion or not $Path
20428 or not -e $Path) {
20429 return "";
20430 }
20431 if(-d $Path)
20432 { # directory with headers files and shared objects
20433 return "
20434 <version>
20435 ".$TargetVersion{$LibVersion}."
20436 </version>
20437
20438 <headers>
20439 $Path
20440 </headers>
20441
20442 <libs>
20443 $Path
20444 </libs>";
20445 }
20446 else
20447 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020448 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020449 { # standard XML-descriptor
20450 return readFile($Path);
20451 }
20452 elsif(is_header($Path, 2, $LibVersion))
20453 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020454 $CheckHeadersOnly = 1;
20455
20456 if($LibVersion==1) {
20457 $TargetVersion{$LibVersion} = "X";
20458 }
20459
20460 if($LibVersion==2) {
20461 $TargetVersion{$LibVersion} = "Y";
20462 }
20463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020464 return "
20465 <version>
20466 ".$TargetVersion{$LibVersion}."
20467 </version>
20468
20469 <headers>
20470 $Path
20471 </headers>
20472
20473 <libs>
20474 none
20475 </libs>";
20476 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020477 else
20478 { # standard XML-descriptor
20479 return readFile($Path);
20480 }
20481 }
20482}
20483
20484sub detect_lib_default_paths()
20485{
20486 my %LPaths = ();
20487 if($OSgroup eq "bsd")
20488 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020489 if(my $LdConfig = get_CmdPath("ldconfig"))
20490 {
20491 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20492 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020493 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20494 {
20495 my $Name = "lib".$1;
20496 if(not defined $LPaths{$Name}) {
20497 $LPaths{$Name} = $2;
20498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020499 }
20500 }
20501 }
20502 else {
20503 printMsg("WARNING", "can't find ldconfig");
20504 }
20505 }
20506 else
20507 {
20508 if(my $LdConfig = get_CmdPath("ldconfig"))
20509 {
20510 if($SystemRoot and $OSgroup eq "linux")
20511 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20512 if(-e $SystemRoot."/etc/ld.so.conf") {
20513 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20514 }
20515 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020516 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20517 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20519 {
20520 my ($Name, $Path) = ($1, $2);
20521 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020522 if(not defined $LPaths{$Name})
20523 { # get first element from the list of available paths
20524
20525 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20526 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20527 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20528
20529 $LPaths{$Name} = $Path;
20530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020531 }
20532 }
20533 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020534 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020535 printMsg("WARNING", "can't find ldconfig");
20536 }
20537 }
20538 return \%LPaths;
20539}
20540
20541sub detect_bin_default_paths()
20542{
20543 my $EnvPaths = $ENV{"PATH"};
20544 if($OSgroup eq "beos") {
20545 $EnvPaths.=":".$ENV{"BETOOLS"};
20546 }
20547 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020548 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 {
20550 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020551 next if(not $Path);
20552 if($SystemRoot
20553 and $Path=~/\A\Q$SystemRoot\E\//)
20554 { # do NOT use binaries from target system
20555 next;
20556 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020557 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020558 }
20559}
20560
20561sub detect_inc_default_paths()
20562{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020563 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020564 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020565 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020566 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020567 next if(index($Line, "/cc1plus ")!=-1);
20568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020569 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20570 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020571 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020572 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020573 if(index($Path, "c++")!=-1
20574 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020575 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020576 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020577 if(not defined $MAIN_CPP_DIR
20578 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20579 $MAIN_CPP_DIR = $Path;
20580 }
20581 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020582 elsif(index($Path, "gcc")!=-1) {
20583 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 }
20585 else
20586 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020587 if($Path=~/local[\/\\]+include/)
20588 { # local paths
20589 next;
20590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 if($SystemRoot
20592 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20593 { # The GCC include path for user headers is not a part of the system root
20594 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20595 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20596 next;
20597 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020598 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020599 }
20600 }
20601 }
20602 unlink("$TMP_DIR/empty.h");
20603 return %DPaths;
20604}
20605
20606sub detect_default_paths($)
20607{
20608 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20609 my $Search = $_[0];
20610 if($Search!~/inc/) {
20611 $HSearch = 0;
20612 }
20613 if($Search!~/lib/) {
20614 $LSearch = 0;
20615 }
20616 if($Search!~/bin/) {
20617 $BSearch = 0;
20618 }
20619 if($Search!~/gcc/) {
20620 $GSearch = 0;
20621 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020622 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020623 { # <search_headers> section of the XML descriptor
20624 # do NOT search for systems headers
20625 $HSearch = 0;
20626 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020627 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020628 { # <search_libs> section of the XML descriptor
20629 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020630 $LSearch = 0;
20631 }
20632 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20633 { # additional search paths
20634 next if($Type eq "include" and not $HSearch);
20635 next if($Type eq "lib" and not $LSearch);
20636 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020637 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020638 }
20639 if($OSgroup ne "windows")
20640 { # unix-like
20641 foreach my $Type ("include", "lib", "bin")
20642 { # automatic detection of system "devel" directories
20643 next if($Type eq "include" and not $HSearch);
20644 next if($Type eq "lib" and not $LSearch);
20645 next if($Type eq "bin" and not $BSearch);
20646 my ($UsrDir, $RootDir) = ("/usr", "/");
20647 if($SystemRoot and $Type ne "bin")
20648 { # 1. search for target headers and libraries
20649 # 2. use host commands: ldconfig, readelf, etc.
20650 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20651 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020652 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020653 if(-d $RootDir."/".$Type)
20654 { # if "/lib" is symbolic link
20655 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020656 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020657 }
20658 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020659 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020660 }
20661 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020662 if(-d $UsrDir)
20663 {
20664 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 if(-d $UsrDir."/".$Type)
20666 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020667 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020668 }
20669 }
20670 }
20671 }
20672 if($BSearch)
20673 {
20674 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020675 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020676 }
20677 # check environment variables
20678 if($OSgroup eq "beos")
20679 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020680 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020681 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020682 if($_ eq ".") {
20683 next;
20684 }
20685 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20686 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20687 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020688 }
20689 }
20690 if($HSearch)
20691 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020692 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20693 split(/:|;/, $ENV{"BEINCLUDES"})
20694 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020695 }
20696 if($LSearch)
20697 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020698 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20699 split(/:|;/, $ENV{"BELIBRARIES"}),
20700 split(/:|;/, $ENV{"LIBRARY_PATH"})
20701 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020702 }
20703 }
20704 if($LSearch)
20705 { # using linker to get system paths
20706 if(my $LPaths = detect_lib_default_paths())
20707 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020708 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 foreach my $Name (keys(%{$LPaths}))
20710 {
20711 if($SystemRoot
20712 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20713 { # wrong ldconfig configuration
20714 # check your <sysroot>/etc/ld.so.conf
20715 next;
20716 }
20717 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020718 if(my $Dir = get_dirname($LPaths->{$Name})) {
20719 $Dirs{$Dir} = 1;
20720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020721 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020722 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020723 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020724 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020725 }
20726 if($BSearch)
20727 {
20728 if($CrossGcc)
20729 { # --cross-gcc=arm-linux-gcc
20730 if(-e $CrossGcc)
20731 { # absolute or relative path
20732 $GCC_PATH = get_abs_path($CrossGcc);
20733 }
20734 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20735 { # command name
20736 $GCC_PATH = $CrossGcc;
20737 }
20738 else {
20739 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20740 }
20741 if($GCC_PATH=~/\s/) {
20742 $GCC_PATH = "\"".$GCC_PATH."\"";
20743 }
20744 }
20745 }
20746 if($GSearch)
20747 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020748 if(not $CrossGcc)
20749 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020750 $GCC_PATH = get_CmdPath("gcc");
20751 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020752 if(not $GCC_PATH)
20753 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020754 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020755 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020756 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020757 { # select the latest version
20758 @GCCs = sort {$b cmp $a} @GCCs;
20759 if(check_gcc($GCCs[0], "3"))
20760 {
20761 $GCC_PATH = $GCCs[0];
20762 last;
20763 }
20764 }
20765 }
20766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020767 if(not $GCC_PATH) {
20768 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20769 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020770
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020771 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020773 my $GccTarget = get_dumpmachine($GCC_PATH);
20774
20775 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020777 $OStarget = "linux";
20778 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020779 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020780 elsif($GccTarget=~/symbian/)
20781 {
20782 $OStarget = "symbian";
20783 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20784 }
20785
20786 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20787
20788 # check GCC version
20789 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20790 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20791 # introduced in 4.8
20792 # fixed in 4.8.3
20793 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20794 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020795 }
20796 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020797 else {
20798 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020799 }
20800 }
20801 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020802 {
20803 # GCC standard paths
20804 if($GCC_PATH and not $NoStdInc)
20805 {
20806 my %DPaths = detect_inc_default_paths();
20807 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20808 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20809 @DefaultIncPaths = @{$DPaths{"Inc"}};
20810 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20811 }
20812
20813 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020814 my $IncPath = "/usr/include";
20815 if($SystemRoot) {
20816 $IncPath = $SystemRoot.$IncPath;
20817 }
20818 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020819 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020820 }
20821 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020822
20823 if($ExtraInfo)
20824 {
20825 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20826 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020828}
20829
20830sub getLIB_EXT($)
20831{
20832 my $Target = $_[0];
20833 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20834 return $Ext;
20835 }
20836 return $OS_LibExt{$LIB_TYPE}{"default"};
20837}
20838
20839sub getAR_EXT($)
20840{
20841 my $Target = $_[0];
20842 if(my $Ext = $OS_Archive{$Target}) {
20843 return $Ext;
20844 }
20845 return $OS_Archive{"default"};
20846}
20847
20848sub get_dumpversion($)
20849{
20850 my $Cmd = $_[0];
20851 return "" if(not $Cmd);
20852 if($Cache{"get_dumpversion"}{$Cmd}) {
20853 return $Cache{"get_dumpversion"}{$Cmd};
20854 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020855 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020856 chomp($V);
20857 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20858}
20859
20860sub get_dumpmachine($)
20861{
20862 my $Cmd = $_[0];
20863 return "" if(not $Cmd);
20864 if($Cache{"get_dumpmachine"}{$Cmd}) {
20865 return $Cache{"get_dumpmachine"}{$Cmd};
20866 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020867 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020868 chomp($Machine);
20869 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20870}
20871
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020872sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020873{
20874 my $Cmd = $_[0];
20875 return "" if(not $Cmd);
20876 my @Options = (
20877 "--version",
20878 "-help"
20879 );
20880 foreach my $Opt (@Options)
20881 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020882 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 if($Info) {
20884 return 1;
20885 }
20886 }
20887 return 0;
20888}
20889
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020890sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020892 my ($Cmd, $ReqVer) = @_;
20893 return 0 if(not $Cmd or not $ReqVer);
20894 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20895 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020896 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020897 if(my $GccVer = get_dumpversion($Cmd))
20898 {
20899 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20900 if(cmpVersions($GccVer, $ReqVer)>=0) {
20901 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20902 }
20903 }
20904 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020905}
20906
20907sub get_depth($)
20908{
20909 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020910 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020911 }
20912 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20913}
20914
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020915sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020916{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020917 return if($Cache{"registerGccHeaders"}); # this function should be called once
20918
20919 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020920 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020921 my @Headers = cmd_find($Path,"f");
20922 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20923 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020924 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020925 my $FileName = get_filename($HPath);
20926 if(not defined $DefaultGccHeader{$FileName})
20927 { # skip duplicated
20928 $DefaultGccHeader{$FileName} = $HPath;
20929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020930 }
20931 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020932 $Cache{"registerGccHeaders"} = 1;
20933}
20934
20935sub registerCppHeaders()
20936{
20937 return if($Cache{"registerCppHeaders"}); # this function should be called once
20938
20939 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020940 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020941 my @Headers = cmd_find($CppDir,"f");
20942 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20943 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020944 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020945 my $FileName = get_filename($Path);
20946 if(not defined $DefaultCppHeader{$FileName})
20947 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020948 $DefaultCppHeader{$FileName} = $Path;
20949 }
20950 }
20951 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953}
20954
20955sub parse_libname($$$)
20956{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020957 return "" if(not $_[0]);
20958 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20959 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020960 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020961 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20962}
20963
20964sub parse_libname_I($$$)
20965{
20966 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020968 if($Target eq "symbian") {
20969 return parse_libname_symbian($Name, $Type);
20970 }
20971 elsif($Target eq "windows") {
20972 return parse_libname_windows($Name, $Type);
20973 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020974
20975 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020977 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020978 { # libSDL-1.2.so.0.7.1
20979 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020980 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020981 if($Type eq "name")
20982 { # libSDL-1.2
20983 # libwbxml2
20984 return $2;
20985 }
20986 elsif($Type eq "name+ext")
20987 { # libSDL-1.2.so
20988 # libwbxml2.so
20989 return $1;
20990 }
20991 elsif($Type eq "version")
20992 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020993 if(defined $7
20994 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020995 { # 0.7.1
20996 return $7;
20997 }
20998 else
20999 { # libc-2.5.so (=>2.5 version)
21000 my $MV = $5;
21001 $MV=~s/\A[\-\_]+//g;
21002 return $MV;
21003 }
21004 }
21005 elsif($Type eq "short")
21006 { # libSDL
21007 # libwbxml2
21008 return $3;
21009 }
21010 elsif($Type eq "shortest")
21011 { # SDL
21012 # wbxml
21013 return shortest_name($3);
21014 }
21015 }
21016 return "";# error
21017}
21018
21019sub parse_libname_symbian($$)
21020{
21021 my ($Name, $Type) = @_;
21022 my $Ext = getLIB_EXT("symbian");
21023 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21024 { # libpthread{00010001}.dso
21025 if($Type eq "name")
21026 { # libpthread{00010001}
21027 return $2;
21028 }
21029 elsif($Type eq "name+ext")
21030 { # libpthread{00010001}.dso
21031 return $1;
21032 }
21033 elsif($Type eq "version")
21034 { # 00010001
21035 my $V = $4;
21036 $V=~s/\{(.+)\}/$1/;
21037 return $V;
21038 }
21039 elsif($Type eq "short")
21040 { # libpthread
21041 return $3;
21042 }
21043 elsif($Type eq "shortest")
21044 { # pthread
21045 return shortest_name($3);
21046 }
21047 }
21048 return "";# error
21049}
21050
21051sub parse_libname_windows($$)
21052{
21053 my ($Name, $Type) = @_;
21054 my $Ext = getLIB_EXT("windows");
21055 if($Name=~/((.+?)\.$Ext)\Z/)
21056 { # netapi32.dll
21057 if($Type eq "name")
21058 { # netapi32
21059 return $2;
21060 }
21061 elsif($Type eq "name+ext")
21062 { # netapi32.dll
21063 return $1;
21064 }
21065 elsif($Type eq "version")
21066 { # DLL version embedded
21067 # at binary-level
21068 return "";
21069 }
21070 elsif($Type eq "short")
21071 { # netapi32
21072 return $2;
21073 }
21074 elsif($Type eq "shortest")
21075 { # netapi
21076 return shortest_name($2);
21077 }
21078 }
21079 return "";# error
21080}
21081
21082sub shortest_name($)
21083{
21084 my $Name = $_[0];
21085 # remove prefix
21086 $Name=~s/\A(lib|open)//;
21087 # remove suffix
21088 $Name=~s/[\W\d_]+\Z//i;
21089 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21090 return $Name;
21091}
21092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021093sub createSymbolsList($$$$$)
21094{
21095 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021096
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021097 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021098 prepareSymbols(1);
21099
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021100 my %SymbolHeaderLib = ();
21101 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021102
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021103 # Get List
21104 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21105 {
21106 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021107 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021108 next;
21109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021110 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021111 { # skip other symbols
21112 next;
21113 }
21114 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21115 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021116 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021117 next;
21118 }
21119 my $DyLib = $Symbol_Library{1}{$Symbol};
21120 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021121 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021122 next;
21123 }
21124 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21125 $Total+=1;
21126 }
21127 # Draw List
21128 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21129 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21130 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21131 {
21132 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21133 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021134 my %NS_Symbol = ();
21135 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021136 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021137 }
21138 foreach my $NameSpace (sort keys(%NS_Symbol))
21139 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021140 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021141 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21142 foreach my $Symbol (@SortedInterfaces)
21143 {
21144 my $SubReport = "";
21145 my $Signature = get_Signature($Symbol, 1);
21146 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021147 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021148 }
21149 if($Symbol=~/\A(_Z|\?)/)
21150 {
21151 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021152 $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 +040021153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021154 else {
21155 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21156 }
21157 }
21158 else
21159 {
21160 if($Signature) {
21161 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21162 }
21163 else {
21164 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21165 }
21166 }
21167 $SYMBOLS_LIST .= $SubReport;
21168 }
21169 }
21170 $SYMBOLS_LIST .= "<br/>\n";
21171 }
21172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021173 # clear info
21174 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21175 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21176 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21177 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021178 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021179 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021180 my $CssStyles = readModule("Styles", "SymbolsList.css");
21181 my $JScripts = readModule("Scripts", "Sections.js");
21182 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021183 my $Title = "$LName: public symbols";
21184 my $Keywords = "$LName, API, symbols";
21185 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021186 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021187 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021188 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021189 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021190 writeFile($SaveTo, $SYMBOLS_LIST);
21191}
21192
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021193sub add_target_libs($)
21194{
21195 foreach (@{$_[0]}) {
21196 $TargetLibs{$_} = 1;
21197 }
21198}
21199
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021200sub is_target_lib($)
21201{
21202 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021203 if(not $LName) {
21204 return 0;
21205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021206 if($TargetLibraryName
21207 and $LName!~/\Q$TargetLibraryName\E/) {
21208 return 0;
21209 }
21210 if(keys(%TargetLibs)
21211 and not $TargetLibs{$LName}
21212 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21213 return 0;
21214 }
21215 return 1;
21216}
21217
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021218sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021219{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021220 my ($H, $V) = @_;
21221 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021222 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021223 if($TargetHeaders{$V}{$H}) {
21224 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021225 }
21226 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021227 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021228}
21229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021230sub readLibs($)
21231{
21232 my $LibVersion = $_[0];
21233 if($OStarget eq "windows")
21234 { # dumpbin.exe will crash
21235 # without VS Environment
21236 check_win32_env();
21237 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021238 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021239 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021240 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021241}
21242
21243sub dump_sorting($)
21244{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021245 my $Hash = $_[0];
21246 return [] if(not $Hash);
21247 my @Keys = keys(%{$Hash});
21248 return [] if($#Keys<0);
21249 if($Keys[0]=~/\A\d+\Z/)
21250 { # numbers
21251 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021253 else
21254 { # strings
21255 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021256 }
21257}
21258
21259sub printMsg($$)
21260{
21261 my ($Type, $Msg) = @_;
21262 if($Type!~/\AINFO/) {
21263 $Msg = $Type.": ".$Msg;
21264 }
21265 if($Type!~/_C\Z/) {
21266 $Msg .= "\n";
21267 }
21268 if($Quiet)
21269 { # --quiet option
21270 appendFile($COMMON_LOG_PATH, $Msg);
21271 }
21272 else
21273 {
21274 if($Type eq "ERROR") {
21275 print STDERR $Msg;
21276 }
21277 else {
21278 print $Msg;
21279 }
21280 }
21281}
21282
21283sub exitStatus($$)
21284{
21285 my ($Code, $Msg) = @_;
21286 printMsg("ERROR", $Msg);
21287 exit($ERROR_CODE{$Code});
21288}
21289
21290sub exitReport()
21291{ # the tool has run without any errors
21292 printReport();
21293 if($COMPILE_ERRORS)
21294 { # errors in headers may add false positives/negatives
21295 exit($ERROR_CODE{"Compile_Error"});
21296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021297 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21298 { # --binary
21299 exit($ERROR_CODE{"Incompatible"});
21300 }
21301 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21302 { # --source
21303 exit($ERROR_CODE{"Incompatible"});
21304 }
21305 elsif($RESULT{"Source"}{"Problems"}
21306 or $RESULT{"Binary"}{"Problems"})
21307 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308 exit($ERROR_CODE{"Incompatible"});
21309 }
21310 else {
21311 exit($ERROR_CODE{"Compatible"});
21312 }
21313}
21314
21315sub readRules($)
21316{
21317 my $Kind = $_[0];
21318 if(not -f $RULES_PATH{$Kind}) {
21319 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21320 }
21321 my $Content = readFile($RULES_PATH{$Kind});
21322 while(my $Rule = parseTag(\$Content, "rule"))
21323 {
21324 my $RId = parseTag(\$Rule, "id");
21325 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21326 foreach my $Prop (@Properties) {
21327 if(my $Value = parseTag(\$Rule, lc($Prop)))
21328 {
21329 $Value=~s/\n[ ]*//;
21330 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21331 }
21332 }
21333 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21334 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21335 }
21336 else {
21337 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21338 }
21339 }
21340}
21341
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021342sub getReportPath($)
21343{
21344 my $Level = $_[0];
21345 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21346 if($Level eq "Binary")
21347 {
21348 if($BinaryReportPath)
21349 { # --bin-report-path
21350 return $BinaryReportPath;
21351 }
21352 elsif($OutputReportPath)
21353 { # --report-path
21354 return $OutputReportPath;
21355 }
21356 else
21357 { # default
21358 return $Dir."/abi_compat_report.$ReportFormat";
21359 }
21360 }
21361 elsif($Level eq "Source")
21362 {
21363 if($SourceReportPath)
21364 { # --src-report-path
21365 return $SourceReportPath;
21366 }
21367 elsif($OutputReportPath)
21368 { # --report-path
21369 return $OutputReportPath;
21370 }
21371 else
21372 { # default
21373 return $Dir."/src_compat_report.$ReportFormat";
21374 }
21375 }
21376 else
21377 {
21378 if($OutputReportPath)
21379 { # --report-path
21380 return $OutputReportPath;
21381 }
21382 else
21383 { # default
21384 return $Dir."/compat_report.$ReportFormat";
21385 }
21386 }
21387}
21388
21389sub printStatMsg($)
21390{
21391 my $Level = $_[0];
21392 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21393}
21394
21395sub listAffected($)
21396{
21397 my $Level = $_[0];
21398 my $List = "";
21399 foreach (keys(%{$TotalAffected{$Level}}))
21400 {
21401 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21402 { # skip "Low"-severity problems
21403 next;
21404 }
21405 $List .= "$_\n";
21406 }
21407 my $Dir = get_dirname(getReportPath($Level));
21408 if($Level eq "Binary") {
21409 writeFile($Dir."/abi_affected.txt", $List);
21410 }
21411 elsif($Level eq "Source") {
21412 writeFile($Dir."/src_affected.txt", $List);
21413 }
21414}
21415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021416sub printReport()
21417{
21418 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021419 createReport();
21420 if($JoinReport or $DoubleReport)
21421 {
21422 if($RESULT{"Binary"}{"Problems"}
21423 or $RESULT{"Source"}{"Problems"}) {
21424 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021425 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021426 else {
21427 printMsg("INFO", "result: COMPATIBLE");
21428 }
21429 printStatMsg("Binary");
21430 printStatMsg("Source");
21431 if($ListAffected)
21432 { # --list-affected
21433 listAffected("Binary");
21434 listAffected("Source");
21435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021436 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021437 elsif($BinaryOnly)
21438 {
21439 if($RESULT{"Binary"}{"Problems"}) {
21440 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21441 }
21442 else {
21443 printMsg("INFO", "result: COMPATIBLE");
21444 }
21445 printStatMsg("Binary");
21446 if($ListAffected)
21447 { # --list-affected
21448 listAffected("Binary");
21449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021450 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021451 elsif($SourceOnly)
21452 {
21453 if($RESULT{"Source"}{"Problems"}) {
21454 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21455 }
21456 else {
21457 printMsg("INFO", "result: COMPATIBLE");
21458 }
21459 printStatMsg("Source");
21460 if($ListAffected)
21461 { # --list-affected
21462 listAffected("Source");
21463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021464 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021465 if($StdOut)
21466 {
21467 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021468 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021469 printMsg("INFO", "compatibility report has been generated to stdout");
21470 }
21471 else
21472 { # default
21473 printMsg("INFO", "compatibility reports have been generated to stdout");
21474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021475 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021476 else
21477 {
21478 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021479 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021480 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21481 }
21482 elsif($DoubleReport)
21483 { # default
21484 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21485 }
21486 elsif($BinaryOnly)
21487 { # --binary
21488 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21489 }
21490 elsif($SourceOnly)
21491 { # --source
21492 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021494 }
21495}
21496
21497sub check_win32_env()
21498{
21499 if(not $ENV{"DevEnvDir"}
21500 or not $ENV{"LIB"}) {
21501 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21502 }
21503}
21504
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021505sub diffSets($$)
21506{
21507 my ($S1, $S2) = @_;
21508 my @SK1 = keys(%{$S1});
21509 my @SK2 = keys(%{$S2});
21510 if($#SK1!=$#SK2) {
21511 return 1;
21512 }
21513 foreach my $K1 (@SK1)
21514 {
21515 if(not defined $S2->{$K1}) {
21516 return 1;
21517 }
21518 }
21519 return 0;
21520}
21521
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021522sub defaultDumpPath($$)
21523{
21524 my ($N, $V) = @_;
21525 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21526}
21527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021528sub create_ABI_Dump()
21529{
21530 if(not -e $DumpAPI) {
21531 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21532 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021533
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021534 if(isDump($DumpAPI)) {
21535 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021536 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021537 else {
21538 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021539 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021540
21541 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021542 { # set to default: N
21543 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021544 }
21545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021546 initLogging(1);
21547 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021548
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021549 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021550 if($OutputDumpPath)
21551 { # user defined path
21552 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021553 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021554 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21555
21556 if(not $Archive and not $StdOut)
21557 { # check archive utilities
21558 if($OSgroup eq "windows")
21559 { # using zip
21560 my $ZipCmd = get_CmdPath("zip");
21561 if(not $ZipCmd) {
21562 exitStatus("Not_Found", "can't find \"zip\"");
21563 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021564 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021565 else
21566 { # using tar and gzip
21567 my $TarCmd = get_CmdPath("tar");
21568 if(not $TarCmd) {
21569 exitStatus("Not_Found", "can't find \"tar\"");
21570 }
21571 my $GzipCmd = get_CmdPath("gzip");
21572 if(not $GzipCmd) {
21573 exitStatus("Not_Found", "can't find \"gzip\"");
21574 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021575 }
21576 }
21577
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021578 if(not $Descriptor{1}{"Dump"})
21579 {
21580 if(not $CheckHeadersOnly) {
21581 readLibs(1);
21582 }
21583 if($CheckHeadersOnly) {
21584 setLanguage(1, "C++");
21585 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021586 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021587 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021588 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021589 if(not $Descriptor{1}{"Dump"})
21590 {
21591 if($Descriptor{1}{"Headers"}) {
21592 readHeaders(1);
21593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021595 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021596 if(not keys(%{$SymbolInfo{1}}))
21597 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021598 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021599 {
21600 if($CheckHeadersOnly) {
21601 exitStatus("Empty_Set", "the set of public symbols is empty");
21602 }
21603 else {
21604 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21605 }
21606 }
21607 }
21608 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021609 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021610 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21611 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021612 if($ExtraDump)
21613 { # add unmangled names to the ABI dump
21614 my @Names = ();
21615 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21616 {
21617 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21618 push(@Names, $MnglName);
21619 }
21620 }
21621 translateSymbols(@Names, 1);
21622 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21623 {
21624 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21625 {
21626 if(my $Unmangled = $tr_name{$MnglName})
21627 {
21628 if($MnglName ne $Unmangled) {
21629 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21630 }
21631 }
21632 }
21633 }
21634 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021635
21636 my %GccConstants = (); # built-in GCC constants
21637 foreach my $Name (keys(%{$Constants{1}}))
21638 {
21639 if(not defined $Constants{1}{$Name}{"Header"})
21640 {
21641 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21642 delete($Constants{1}{$Name});
21643 }
21644 }
21645
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021646 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021647 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021648 "TypeInfo" => $TypeInfo{1},
21649 "SymbolInfo" => $SymbolInfo{1},
21650 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021651 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021652 "SymbolVersion" => $SymVer{1},
21653 "LibraryVersion" => $Descriptor{1}{"Version"},
21654 "LibraryName" => $TargetLibraryName,
21655 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021656 "SkipTypes" => $SkipTypes{1},
21657 "SkipSymbols" => $SkipSymbols{1},
21658 "SkipNameSpaces" => $SkipNameSpaces{1},
21659 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021660 "Headers" => \%HeadersInfo,
21661 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021662 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021663 "NameSpaces" => $NestedNameSpaces{1},
21664 "Target" => $OStarget,
21665 "Arch" => getArch(1),
21666 "WordSize" => $WORD_SIZE{1},
21667 "GccVersion" => get_dumpversion($GCC_PATH),
21668 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21669 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21670 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021671 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021672 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021673 }
21674 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021675 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021677 if($ExtendedCheck)
21678 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021679 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021681 if($BinaryOnly)
21682 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021683 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021684 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021685 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021686 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021687 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021688 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21689 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021690 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021691
21692 my $ABI_DUMP = "";
21693 if($UseXML)
21694 {
21695 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021696 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021698 else
21699 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021700 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021702 if($StdOut)
21703 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021704 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021705 printMsg("INFO", "ABI dump has been generated to stdout");
21706 return;
21707 }
21708 else
21709 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021710 my ($DDir, $DName) = separate_path($DumpPath);
21711 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021712 if(not $Archive) {
21713 $DPath = $DumpPath;
21714 }
21715
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021716 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021717
21718 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021719 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021720 close(DUMP);
21721
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021722 if(not -s $DPath) {
21723 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21724 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021725 if($Archive) {
21726 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021727 }
21728
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021729 if($OutputDumpPath) {
21730 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021731 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021732 else {
21733 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21734 }
21735 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 +040021736 }
21737}
21738
21739sub quickEmptyReports()
21740{ # Quick "empty" reports
21741 # 4 times faster than merging equal dumps
21742 # NOTE: the dump contains the "LibraryVersion" attribute
21743 # if you change the version, then your dump will be different
21744 # OVERCOME: use -v1 and v2 options for comparing dumps
21745 # and don't change version in the XML descriptor (and dumps)
21746 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21747 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21748 {
21749 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21750 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21751 if($FilePath1 and $FilePath2)
21752 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021753 my $Line = readLineNum($FilePath1, 0);
21754 if($Line=~/xml/)
21755 { # XML format
21756 # is not supported yet
21757 return;
21758 }
21759
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021760 local $/ = undef;
21761
21762 open(DUMP1, $FilePath1);
21763 my $Content1 = <DUMP1>;
21764 close(DUMP1);
21765
21766 open(DUMP2, $FilePath2);
21767 my $Content2 = <DUMP2>;
21768 close(DUMP2);
21769
21770 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021771 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021772 # clean memory
21773 undef $Content2;
21774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021775 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021776 my $ABIdump = eval($Content1);
21777
21778 # clean memory
21779 undef $Content1;
21780
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021781 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021782 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 +040021783 }
21784 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021785 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021786 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21787 }
21788 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021789 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021792 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021793 read_Libs_DumpInfo($ABIdump, 1);
21794 read_Machine_DumpInfo($ABIdump, 1);
21795 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021796
21797 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21798 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21799
21800 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21801 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21802
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021803 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21804 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21805 exitReport();
21806 }
21807 }
21808 }
21809}
21810
21811sub initLogging($)
21812{
21813 my $LibVersion = $_[0];
21814 # create log directory
21815 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21816 if($OutputLogPath{$LibVersion})
21817 { # user-defined by -log-path option
21818 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21819 }
21820 if($LogMode ne "n") {
21821 mkpath($LOG_DIR);
21822 }
21823 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021824 if($Debug)
21825 { # debug directory
21826 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021827
21828 if(not $ExtraInfo)
21829 { # enable --extra-info
21830 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021832 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021833 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021834}
21835
21836sub writeLog($$)
21837{
21838 my ($LibVersion, $Msg) = @_;
21839 if($LogMode ne "n") {
21840 appendFile($LOG_PATH{$LibVersion}, $Msg);
21841 }
21842}
21843
21844sub resetLogging($)
21845{
21846 my $LibVersion = $_[0];
21847 if($LogMode!~/a|n/)
21848 { # remove old log
21849 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021850 if($Debug) {
21851 rmtree($DEBUG_PATH{$LibVersion});
21852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021853 }
21854}
21855
21856sub printErrorLog($)
21857{
21858 my $LibVersion = $_[0];
21859 if($LogMode ne "n") {
21860 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21861 }
21862}
21863
21864sub isDump($)
21865{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021866 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21867 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021868 return $1;
21869 }
21870 return 0;
21871}
21872
21873sub isDump_U($)
21874{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021875 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021876 return $1;
21877 }
21878 return 0;
21879}
21880
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021881sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021882{
21883 # read input XML descriptors or ABI dumps
21884 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021885 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021887 if(not -e $Descriptor{1}{"Path"}) {
21888 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021889 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021890
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021891 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021892 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021893 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021894 if(not -e $Descriptor{2}{"Path"}) {
21895 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021896 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021897
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021899 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021900 and isDump($Descriptor{2}{"Path"}))
21901 { # optimization: equal ABI dumps
21902 quickEmptyReports();
21903 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021904
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021905 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021906
21907 if(isDump($Descriptor{1}{"Path"})) {
21908 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021909 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021910 else {
21911 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21912 }
21913
21914 if(isDump($Descriptor{2}{"Path"})) {
21915 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21916 }
21917 else {
21918 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021919 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021920
21921 if(not $Descriptor{1}{"Version"})
21922 { # set to default: X
21923 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021924 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021925 }
21926
21927 if(not $Descriptor{2}{"Version"})
21928 { # set to default: Y
21929 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021930 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021931 }
21932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021933 initLogging(1);
21934 initLogging(2);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021935
21936 # check input data
21937 if(not $Descriptor{1}{"Headers"}) {
21938 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021939 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021940 if(not $Descriptor{2}{"Headers"}) {
21941 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021942 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021943
21944 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021945 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021946 if(not $Descriptor{1}{"Libs"}) {
21947 exitStatus("Error", "can't find libraries info in descriptor d1");
21948 }
21949 if(not $Descriptor{2}{"Libs"}) {
21950 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021951 }
21952 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021953
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021954 if($UseDumps)
21955 { # --use-dumps
21956 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021957 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21958 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021959
21960 unlink($DumpPath1);
21961 unlink($DumpPath2);
21962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021963 my $pid = fork();
21964 if($pid)
21965 { # dump on two CPU cores
21966 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21967 if($RelativeDirectory{1}) {
21968 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21969 }
21970 if($OutputLogPath{1}) {
21971 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21972 }
21973 if($CrossGcc) {
21974 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21975 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021976 if($Quiet)
21977 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021978 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021979 @PARAMS = (@PARAMS, "-logging-mode", "a");
21980 }
21981 elsif($LogMode and $LogMode ne "w")
21982 { # "w" is default
21983 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021984 }
21985 if($ExtendedCheck) {
21986 @PARAMS = (@PARAMS, "-extended");
21987 }
21988 if($UserLang) {
21989 @PARAMS = (@PARAMS, "-lang", $UserLang);
21990 }
21991 if($TargetVersion{1}) {
21992 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21993 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021994 if($BinaryOnly) {
21995 @PARAMS = (@PARAMS, "-binary");
21996 }
21997 if($SourceOnly) {
21998 @PARAMS = (@PARAMS, "-source");
21999 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022000 if($SortDump) {
22001 @PARAMS = (@PARAMS, "-sort");
22002 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022003 if($DumpFormat and $DumpFormat ne "perl") {
22004 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22005 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022006 if($CheckHeadersOnly) {
22007 @PARAMS = (@PARAMS, "-headers-only");
22008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022009 if($Debug)
22010 {
22011 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022012 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022014 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022015 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022016 exit(1);
22017 }
22018 }
22019 else
22020 { # child
22021 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22022 if($RelativeDirectory{2}) {
22023 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22024 }
22025 if($OutputLogPath{2}) {
22026 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22027 }
22028 if($CrossGcc) {
22029 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22030 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022031 if($Quiet)
22032 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022033 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022034 @PARAMS = (@PARAMS, "-logging-mode", "a");
22035 }
22036 elsif($LogMode and $LogMode ne "w")
22037 { # "w" is default
22038 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022039 }
22040 if($ExtendedCheck) {
22041 @PARAMS = (@PARAMS, "-extended");
22042 }
22043 if($UserLang) {
22044 @PARAMS = (@PARAMS, "-lang", $UserLang);
22045 }
22046 if($TargetVersion{2}) {
22047 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22048 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022049 if($BinaryOnly) {
22050 @PARAMS = (@PARAMS, "-binary");
22051 }
22052 if($SourceOnly) {
22053 @PARAMS = (@PARAMS, "-source");
22054 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022055 if($SortDump) {
22056 @PARAMS = (@PARAMS, "-sort");
22057 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022058 if($DumpFormat and $DumpFormat ne "perl") {
22059 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22060 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022061 if($CheckHeadersOnly) {
22062 @PARAMS = (@PARAMS, "-headers-only");
22063 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022064 if($Debug)
22065 {
22066 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022067 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022069 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022070 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022071 exit(1);
22072 }
22073 else {
22074 exit(0);
22075 }
22076 }
22077 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022079 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022080 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22081 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022082 if($TargetTitle ne $TargetLibraryName) {
22083 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022084 }
22085 if($ShowRetVal) {
22086 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22087 }
22088 if($CrossGcc) {
22089 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22090 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022091 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22092 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022093 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022094 }
22095 if($ReportFormat and $ReportFormat ne "html")
22096 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022097 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22098 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022099 if($OutputReportPath) {
22100 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22101 }
22102 if($BinaryReportPath) {
22103 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22104 }
22105 if($SourceReportPath) {
22106 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22107 }
22108 if($LoggingPath) {
22109 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22110 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022111 if($CheckHeadersOnly) {
22112 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22113 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022114 if($BinaryOnly) {
22115 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22116 }
22117 if($SourceOnly) {
22118 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22119 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022120 if($Debug)
22121 {
22122 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22123 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022125 system("perl", $0, @CMP_PARAMS);
22126 exit($?>>8);
22127 }
22128 if(not $Descriptor{1}{"Dump"}
22129 or not $Descriptor{2}{"Dump"})
22130 { # need GCC toolchain to analyze
22131 # header files and libraries
22132 detect_default_paths("inc|lib|gcc");
22133 }
22134 if(not $Descriptor{1}{"Dump"})
22135 {
22136 if(not $CheckHeadersOnly) {
22137 readLibs(1);
22138 }
22139 if($CheckHeadersOnly) {
22140 setLanguage(1, "C++");
22141 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022142 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022143 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022144 }
22145 if(not $Descriptor{2}{"Dump"})
22146 {
22147 if(not $CheckHeadersOnly) {
22148 readLibs(2);
22149 }
22150 if($CheckHeadersOnly) {
22151 setLanguage(2, "C++");
22152 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022153 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022154 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022155 }
22156 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22157 { # support for old ABI dumps
22158 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022159 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022160 {
22161 $WORD_SIZE{1} = $WORD_SIZE{2};
22162 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22163 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022164 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022165 {
22166 $WORD_SIZE{2} = $WORD_SIZE{1};
22167 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22168 }
22169 }
22170 elsif(not $WORD_SIZE{1}
22171 and not $WORD_SIZE{2})
22172 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022173 $WORD_SIZE{1} = "4";
22174 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022175 }
22176 if($Descriptor{1}{"Dump"})
22177 { # support for old ABI dumps
22178 prepareTypes(1);
22179 }
22180 if($Descriptor{2}{"Dump"})
22181 { # support for old ABI dumps
22182 prepareTypes(2);
22183 }
22184 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22185 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22186 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022187 # process input data
22188 if($Descriptor{1}{"Headers"}
22189 and not $Descriptor{1}{"Dump"}) {
22190 readHeaders(1);
22191 }
22192 if($Descriptor{2}{"Headers"}
22193 and not $Descriptor{2}{"Dump"}) {
22194 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022196
22197 # clean memory
22198 %SystemHeaders = ();
22199 %mangled_name_gcc = ();
22200
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022201 prepareSymbols(1);
22202 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022203
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022204 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022205 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022206
22207 # Virtual Tables
22208 registerVTable(1);
22209 registerVTable(2);
22210
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022211 if(not checkDump(1, "1.22")
22212 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022213 { # support for old ABI dumps
22214 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22215 {
22216 if($ClassName=~/</)
22217 { # templates
22218 if(not defined $VirtualTable{1}{$ClassName})
22219 { # synchronize
22220 delete($VirtualTable{2}{$ClassName});
22221 }
22222 }
22223 }
22224 }
22225
22226 registerOverriding(1);
22227 registerOverriding(2);
22228
22229 setVirtFuncPositions(1);
22230 setVirtFuncPositions(2);
22231
22232 # Other
22233 addParamNames(1);
22234 addParamNames(2);
22235
22236 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022237}
22238
22239sub compareAPIs($)
22240{
22241 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022242
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022243 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022244 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022245
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022246 if($Level eq "Binary") {
22247 printMsg("INFO", "comparing ABIs ...");
22248 }
22249 else {
22250 printMsg("INFO", "comparing APIs ...");
22251 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022252
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022253 if($CheckHeadersOnly
22254 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022255 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022256 detectAdded_H($Level);
22257 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022258 }
22259 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022260 { # added/removed in libs
22261 detectAdded($Level);
22262 detectRemoved($Level);
22263 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022264
22265 mergeSymbols($Level);
22266 if(keys(%{$CheckedSymbols{$Level}})) {
22267 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022268 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022269
22270 $Cache{"mergeTypes"} = (); # free memory
22271
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022272 if($CheckHeadersOnly
22273 or $Level eq "Source")
22274 { # added/removed in headers
22275 mergeHeaders($Level);
22276 }
22277 else
22278 { # added/removed in libs
22279 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022280 }
22281}
22282
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022283sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022284{
22285 my %Opts = (
22286 "OStarget"=>$OStarget,
22287 "Debug"=>$Debug,
22288 "Quiet"=>$Quiet,
22289 "LogMode"=>$LogMode,
22290 "CheckHeadersOnly"=>$CheckHeadersOnly,
22291
22292 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022293 "GCC_PATH"=>$GCC_PATH,
22294 "TargetSysInfo"=>$TargetSysInfo,
22295 "CrossPrefix"=>$CrossPrefix,
22296 "TargetLibraryName"=>$TargetLibraryName,
22297 "CrossGcc"=>$CrossGcc,
22298 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022299 "NoStdInc"=>$NoStdInc,
22300
22301 "BinaryOnly" => $BinaryOnly,
22302 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022303 );
22304 return \%Opts;
22305}
22306
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022307sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022308{
22309 my %CODE_ERROR = reverse(%ERROR_CODE);
22310 return $CODE_ERROR{$_[0]};
22311}
22312
22313sub scenario()
22314{
22315 if($StdOut)
22316 { # enable quiet mode
22317 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022318 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022320 if(not $LogMode)
22321 { # default
22322 $LogMode = "w";
22323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022324 if($UserLang)
22325 { # --lang=C++
22326 $UserLang = uc($UserLang);
22327 $COMMON_LANGUAGE{1}=$UserLang;
22328 $COMMON_LANGUAGE{2}=$UserLang;
22329 }
22330 if($LoggingPath)
22331 {
22332 $OutputLogPath{1} = $LoggingPath;
22333 $OutputLogPath{2} = $LoggingPath;
22334 if($Quiet) {
22335 $COMMON_LOG_PATH = $LoggingPath;
22336 }
22337 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022338
22339 if($SkipInternalSymbols) {
22340 $SkipInternalSymbols=~s/\*/.*/g;
22341 }
22342
22343 if($SkipInternalTypes) {
22344 $SkipInternalTypes=~s/\*/.*/g;
22345 }
22346
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022347 if($Quick) {
22348 $ADD_TMPL_INSTANCES = 0;
22349 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022350 if($OutputDumpPath)
22351 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022352 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022353 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22354 }
22355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022356 if($BinaryOnly and $SourceOnly)
22357 { # both --binary and --source
22358 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022359 if(not $CmpSystems)
22360 {
22361 $BinaryOnly = 0;
22362 $SourceOnly = 0;
22363 }
22364
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022365 $DoubleReport = 1;
22366 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022367
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022368 if($OutputReportPath)
22369 { # --report-path
22370 $DoubleReport = 0;
22371 $JoinReport = 1;
22372 }
22373 }
22374 elsif($BinaryOnly or $SourceOnly)
22375 { # --binary or --source
22376 $DoubleReport = 0;
22377 $JoinReport = 0;
22378 }
22379 if($UseXML)
22380 { # --xml option
22381 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022382 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022384 if($ReportFormat)
22385 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022386 $ReportFormat = lc($ReportFormat);
22387 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022388 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022390 if($ReportFormat eq "htm")
22391 { # HTM == HTML
22392 $ReportFormat = "html";
22393 }
22394 elsif($ReportFormat eq "xml")
22395 { # --report-format=XML equal to --xml
22396 $UseXML = 1;
22397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022398 }
22399 else
22400 { # default: HTML
22401 $ReportFormat = "html";
22402 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022403 if($DumpFormat)
22404 { # validate
22405 $DumpFormat = lc($DumpFormat);
22406 if($DumpFormat!~/\A(xml|perl)\Z/) {
22407 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22408 }
22409 if($DumpFormat eq "xml")
22410 { # --dump-format=XML equal to --xml
22411 $UseXML = 1;
22412 }
22413 }
22414 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022415 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022416 $DumpFormat = "perl";
22417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022418 if($Quiet and $LogMode!~/a|n/)
22419 { # --quiet log
22420 if(-f $COMMON_LOG_PATH) {
22421 unlink($COMMON_LOG_PATH);
22422 }
22423 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022424 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022425 $CheckUndefined = 1;
22426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022427 if($TestTool and $UseDumps)
22428 { # --test && --use-dumps == --test-dump
22429 $TestDump = 1;
22430 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022431 if($Tolerant)
22432 { # enable all
22433 $Tolerance = 1234;
22434 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022435 if($Help)
22436 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022437 HELP_MESSAGE();
22438 exit(0);
22439 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022440 if($InfoMsg)
22441 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022442 INFO_MESSAGE();
22443 exit(0);
22444 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022445 if($ShowVersion)
22446 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022447 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 +040022448 exit(0);
22449 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022450 if($DumpVersion)
22451 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022452 printMsg("INFO", $TOOL_VERSION);
22453 exit(0);
22454 }
22455 if($ExtendedCheck) {
22456 $CheckHeadersOnly = 1;
22457 }
22458 if($SystemRoot_Opt)
22459 { # user defined root
22460 if(not -e $SystemRoot_Opt) {
22461 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22462 }
22463 $SystemRoot = $SystemRoot_Opt;
22464 $SystemRoot=~s/[\/]+\Z//g;
22465 if($SystemRoot) {
22466 $SystemRoot = get_abs_path($SystemRoot);
22467 }
22468 }
22469 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022470
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022471 if($SortDump)
22472 {
22473 $Data::Dumper::Useperl = 1;
22474 $Data::Dumper::Sortkeys = \&dump_sorting;
22475 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022477 if($TargetLibsPath)
22478 {
22479 if(not -f $TargetLibsPath) {
22480 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22481 }
22482 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22483 $TargetLibs{$Lib} = 1;
22484 }
22485 }
22486 if($TargetHeadersPath)
22487 { # --headers-list
22488 if(not -f $TargetHeadersPath) {
22489 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22490 }
22491 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22492 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022493 $TargetHeaders{1}{get_filename($Header)} = 1;
22494 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022495 }
22496 }
22497 if($TargetHeader)
22498 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022499 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22500 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022501 }
22502 if($TestTool
22503 or $TestDump)
22504 { # --test, --test-dump
22505 detect_default_paths("bin|gcc"); # to compile libs
22506 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022507 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022508 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022509 exit(0);
22510 }
22511 if($DumpSystem)
22512 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022513
22514 if(not $TargetSysInfo) {
22515 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22516 }
22517
22518 if(not -d $TargetSysInfo) {
22519 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22520 }
22521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022522 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022523 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022524 { # system XML descriptor
22525 if(not -f $DumpSystem) {
22526 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22527 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022528
22529 my $SDesc = readFile($DumpSystem);
22530 if(my $RelDir = $RelativeDirectory{1}) {
22531 $SDesc =~ s/{RELPATH}/$RelDir/g;
22532 }
22533
22534 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022535 foreach (@{$Ret->{"Tools"}})
22536 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022537 push_U($SystemPaths{"bin"}, $_);
22538 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022539 }
22540 if($Ret->{"CrossPrefix"}) {
22541 $CrossPrefix = $Ret->{"CrossPrefix"};
22542 }
22543 }
22544 elsif($SystemRoot_Opt)
22545 { # -sysroot "/" option
22546 # default target: /usr/lib, /usr/include
22547 # search libs: /usr/lib and /lib
22548 if(not -e $SystemRoot."/usr/lib") {
22549 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22550 }
22551 if(not -e $SystemRoot."/lib") {
22552 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22553 }
22554 if(not -e $SystemRoot."/usr/include") {
22555 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22556 }
22557 readSystemDescriptor("
22558 <name>
22559 $DumpSystem
22560 </name>
22561 <headers>
22562 $SystemRoot/usr/include
22563 </headers>
22564 <libs>
22565 $SystemRoot/usr/lib
22566 </libs>
22567 <search_libs>
22568 $SystemRoot/lib
22569 </search_libs>");
22570 }
22571 else {
22572 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22573 }
22574 detect_default_paths("bin|gcc"); # to check symbols
22575 if($OStarget eq "windows")
22576 { # to run dumpbin.exe
22577 # and undname.exe
22578 check_win32_env();
22579 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022580 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022581 exit(0);
22582 }
22583 if($CmpSystems)
22584 { # --cmp-systems
22585 detect_default_paths("bin"); # to extract dumps
22586 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022587 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022588 exit(0);
22589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022590 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022591 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022592 }
22593 else
22594 { # validate library name
22595 if($TargetLibraryName=~/[\*\/\\]/) {
22596 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22597 }
22598 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022599 if(not $TargetTitle) {
22600 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022601 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022603 if($SymbolsListPath)
22604 {
22605 if(not -f $SymbolsListPath) {
22606 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22607 }
22608 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22609 $SymbolsList{$Interface} = 1;
22610 }
22611 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022612 if($TypesListPath)
22613 {
22614 if(not -f $TypesListPath) {
22615 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22616 }
22617 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22618 $TypesList{$Type} = 1;
22619 }
22620 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022621 if($SkipSymbolsListPath)
22622 {
22623 if(not -f $SkipSymbolsListPath) {
22624 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22625 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022626 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22627 {
22628 $SkipSymbols{1}{$Interface} = 1;
22629 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022630 }
22631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022632 if($SkipHeadersPath)
22633 {
22634 if(not -f $SkipHeadersPath) {
22635 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22636 }
22637 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022638 { # register for both versions
22639 $SkipHeadersList{1}{$Path} = 1;
22640 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022641 my ($CPath, $Type) = classifyPath($Path);
22642 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022643 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022644 }
22645 }
22646 if($ParamNamesPath)
22647 {
22648 if(not -f $ParamNamesPath) {
22649 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22650 }
22651 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22652 {
22653 if($Line=~s/\A(\w+)\;//)
22654 {
22655 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022656 if($Line=~/;(\d+);/)
22657 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022658 while($Line=~s/(\d+);(\w+)//) {
22659 $AddIntParams{$Interface}{$1}=$2;
22660 }
22661 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022662 else
22663 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022664 my $Num = 0;
22665 foreach my $Name (split(/;/, $Line)) {
22666 $AddIntParams{$Interface}{$Num++}=$Name;
22667 }
22668 }
22669 }
22670 }
22671 }
22672 if($AppPath)
22673 {
22674 if(not -f $AppPath) {
22675 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22676 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022677
22678 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022679 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022680 $SymbolsList_App{$Interface} = 1;
22681 }
22682 }
22683 if($DumpAPI)
22684 { # --dump-abi
22685 # make an API dump
22686 create_ABI_Dump();
22687 exit($COMPILE_ERRORS);
22688 }
22689 # default: compare APIs
22690 # -d1 <path>
22691 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022692 compareInit();
22693 if($JoinReport or $DoubleReport)
22694 {
22695 compareAPIs("Binary");
22696 compareAPIs("Source");
22697 }
22698 elsif($BinaryOnly) {
22699 compareAPIs("Binary");
22700 }
22701 elsif($SourceOnly) {
22702 compareAPIs("Source");
22703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022704 exitReport();
22705}
22706
22707scenario();