blob: abe87e0ef04781601481ac170311b34fc03074f0 [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 Ponomarenko2c530f72015-10-15 01:07:53 +03009782 else {
9783 return 0;
9784 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009785
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009786 if($SkipInternalTypes)
9787 {
9788 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9789 {
9790 return 0;
9791 }
9792 }
9793
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009794 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009795}
9796
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009797sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009798{ # remove unused data types from the ABI dump
9799 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009800
9801 my %UsedType = ();
9802
9803 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009804 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009805 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009806 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009807 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009808 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009809 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009810 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009811 next;
9812 }
9813
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009814 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009815 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009816 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009817 {
9818 my %Tree = ();
9819 register_TypeUsage($Tid, \%Tree, $LibVersion);
9820
9821 my $Tmpl = 0;
9822 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9823 {
9824 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9825 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9826 {
9827 $Tmpl = 1;
9828 last;
9829 }
9830 }
9831 if(not $Tmpl)
9832 {
9833 foreach (keys(%Tree)) {
9834 $UsedType{$_} = 1;
9835 }
9836 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009837 }
9838 }
9839 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009840
9841 my %Delete = ();
9842
9843 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009844 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009845 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009846 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009847 next;
9848 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009849
9850 if($Kind eq "Extra")
9851 {
9852 my %Tree = ();
9853 register_TypeUsage($Tid, \%Tree, $LibVersion);
9854
9855 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9856 {
9857 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9858 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9859 {
9860 $Delete{$Tid} = 1;
9861 last;
9862 }
9863 }
9864 }
9865 else
9866 {
9867 # remove type
9868 delete($TypeInfo{$LibVersion}{$Tid});
9869 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009870 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009871
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009872 if($Kind eq "Extra")
9873 { # remove duplicates
9874 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9875 {
9876 if($UsedType{$Tid})
9877 { # All & Extended
9878 next;
9879 }
9880
9881 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9882
9883 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9884 delete($TypeInfo{$LibVersion}{$Tid});
9885 }
9886 }
9887 }
9888
9889 foreach my $Tid (keys(%Delete))
9890 {
9891 delete($TypeInfo{$LibVersion}{$Tid});
9892 }
9893}
9894
9895sub check_Completeness($$)
9896{
9897 my ($Info, $LibVersion) = @_;
9898
9899 # data types
9900 if(defined $Info->{"Memb"})
9901 {
9902 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9903 {
9904 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9905 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9906 }
9907 }
9908 }
9909 if(defined $Info->{"Base"})
9910 {
9911 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9912 check_TypeInfo($Bid, $LibVersion);
9913 }
9914 }
9915 if(defined $Info->{"BaseType"}) {
9916 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9917 }
9918 if(defined $Info->{"TParam"})
9919 {
9920 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9921 {
9922 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9923 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9924 next;
9925 }
9926 if($TName eq "_BoolType") {
9927 next;
9928 }
9929 if($TName=~/\Asizeof\(/) {
9930 next;
9931 }
9932 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9933 check_TypeInfo($Tid, $LibVersion);
9934 }
9935 else
9936 {
9937 if(defined $Debug) {
9938 printMsg("WARNING", "missed type $TName");
9939 }
9940 }
9941 }
9942 }
9943
9944 # symbols
9945 if(defined $Info->{"Param"})
9946 {
9947 foreach my $Pos (keys(%{$Info->{"Param"}}))
9948 {
9949 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9950 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9951 }
9952 }
9953 }
9954 if(defined $Info->{"Return"}) {
9955 check_TypeInfo($Info->{"Return"}, $LibVersion);
9956 }
9957 if(defined $Info->{"Class"}) {
9958 check_TypeInfo($Info->{"Class"}, $LibVersion);
9959 }
9960}
9961
9962sub check_TypeInfo($$)
9963{
9964 my ($Tid, $LibVersion) = @_;
9965
9966 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9967 return;
9968 }
9969 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9970
9971 if(defined $TypeInfo{$LibVersion}{$Tid})
9972 {
9973 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9974 printMsg("ERROR", "missed type name ($Tid)");
9975 }
9976 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9977 }
9978 else {
9979 printMsg("ERROR", "missed type id $Tid");
9980 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009981}
9982
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009983sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009984{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009985 my ($TypeId, $LibVersion) = @_;
9986 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009987 if($Type{"Type"} eq "Typedef")
9988 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009989 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009990 if($Base{"Type"}=~/Class|Struct/)
9991 {
9992 if($Type{"Name"} eq $Base{"Name"}) {
9993 return 1;
9994 }
9995 elsif($Type{"Name"}=~/::(\w+)\Z/)
9996 {
9997 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9998 { # QPointer<QWidget>::QPointer
9999 return 1;
10000 }
10001 }
10002 }
10003 }
10004 return 0;
10005}
10006
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010007sub addExtension($)
10008{
10009 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010010 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010011 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010012 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010013 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010014 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10015 $TName=~s/\A(struct|union|class|enum) //;
10016 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010017
10018 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10019 "Header" => "extended.h",
10020 "ShortName" => $Symbol,
10021 "MnglName" => $Symbol,
10022 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10023 );
10024
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010025 $ExtendedSymbols{$Symbol} = 1;
10026 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10027 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010028 }
10029 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010030 $ExtendedSymbols{"external_func_0"} = 1;
10031 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10032 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010033}
10034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010035sub findMethod($$$)
10036{
10037 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010038 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010039 {
10040 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10041 return $VirtMethodInClass;
10042 }
10043 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10044 return $VirtMethodInBaseClasses;
10045 }
10046 }
10047 return "";
10048}
10049
10050sub findMethod_Class($$$)
10051{
10052 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010053 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010054 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10055 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10056 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10057 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10058 { # search for interface with the same parameters suffix (overridden)
10059 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10060 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010061 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10062 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010063 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10064 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010065 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10066 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10067 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10068 return $Candidate;
10069 }
10070 }
10071 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010072 else
10073 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010074 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10075 return $Candidate;
10076 }
10077 }
10078 }
10079 }
10080 return "";
10081}
10082
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010083sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010084{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010085 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010086 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010087 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010088 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10089 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010090 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010091 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010092 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010093 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10094 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010095 { # pure virtual D2-destructors are marked as "virt" in the dump
10096 # virtual D2-destructors are NOT marked as "virt" in the dump
10097 # both destructors are not presented in the v-table
10098 next;
10099 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010100 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010101 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010103 }
10104}
10105
10106sub registerOverriding($)
10107{
10108 my $LibVersion = $_[0];
10109 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010110 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010111 foreach my $ClassName (@Classes)
10112 {
10113 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10114 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010115 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10116 { # pure virtuals
10117 next;
10118 }
10119 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10120 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010121 {
10122 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10123 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10124 { # both overridden virtual methods
10125 # and implemented pure virtual methods
10126 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10127 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10128 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010130 }
10131 }
10132 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10133 delete($VirtualTable{$LibVersion}{$ClassName});
10134 }
10135 }
10136}
10137
10138sub setVirtFuncPositions($)
10139{
10140 my $LibVersion = $_[0];
10141 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10142 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010143 my ($Num, $Rel) = (1, 0);
10144
10145 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010146 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010147 if($UsedDump{$LibVersion}{"DWARF"}) {
10148 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10149 }
10150 else {
10151 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10152 }
10153 foreach my $VirtFunc (@Funcs)
10154 {
10155 if($UsedDump{$LibVersion}{"DWARF"}) {
10156 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10157 }
10158 else {
10159 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10160 }
10161
10162 # set relative positions
10163 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10164 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10165 { # relative position excluding added and removed virtual functions
10166 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10167 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10168 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 }
10173 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010174 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010175 {
10176 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010177 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010178 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010179 }
10180 }
10181}
10182
10183sub get_sub_classes($$$)
10184{
10185 my ($ClassId, $LibVersion, $Recursive) = @_;
10186 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10187 my @Subs = ();
10188 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10189 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010190 if($Recursive)
10191 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010192 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10193 push(@Subs, $SubSubId);
10194 }
10195 }
10196 push(@Subs, $SubId);
10197 }
10198 return @Subs;
10199}
10200
10201sub get_base_classes($$$)
10202{
10203 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010204 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010205 return () if(not defined $ClassType{"Base"});
10206 my @Bases = ();
10207 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10208 keys(%{$ClassType{"Base"}}))
10209 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010210 if($Recursive)
10211 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010212 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10213 push(@Bases, $SubBaseId);
10214 }
10215 }
10216 push(@Bases, $BaseId);
10217 }
10218 return @Bases;
10219}
10220
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010221sub getVTable_Model($$)
10222{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010223 my ($ClassId, $LibVersion) = @_;
10224 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10225 my @Elements = ();
10226 foreach my $BaseId (@Bases, $ClassId)
10227 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010228 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010229 {
10230 if(defined $VirtualTable{$LibVersion}{$BName})
10231 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010232 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10233 if($UsedDump{$LibVersion}{"DWARF"}) {
10234 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10235 }
10236 else {
10237 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10238 }
10239 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010240 push(@Elements, $VFunc);
10241 }
10242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010243 }
10244 }
10245 return @Elements;
10246}
10247
10248sub getVShift($$)
10249{
10250 my ($ClassId, $LibVersion) = @_;
10251 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10252 my $VShift = 0;
10253 foreach my $BaseId (@Bases)
10254 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010255 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010256 {
10257 if(defined $VirtualTable{$LibVersion}{$BName}) {
10258 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010260 }
10261 }
10262 return $VShift;
10263}
10264
10265sub getShift($$)
10266{
10267 my ($ClassId, $LibVersion) = @_;
10268 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10269 my $Shift = 0;
10270 foreach my $BaseId (@Bases)
10271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010272 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010273 {
10274 if($Size!=1)
10275 { # not empty base class
10276 $Shift+=$Size;
10277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010278 }
10279 }
10280 return $Shift;
10281}
10282
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010283sub getVTable_Size($$)
10284{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010285 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010286 my $Size = 0;
10287 # three approaches
10288 if(not $Size)
10289 { # real size
10290 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10291 $Size = keys(%VTable);
10292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010293 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010294 if(not $Size)
10295 { # shared library symbol size
10296 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10297 $Size /= $WORD_SIZE{$LibVersion};
10298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010299 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010300 if(not $Size)
10301 { # model size
10302 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10303 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10304 }
10305 }
10306 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010307}
10308
10309sub isCopyingClass($$)
10310{
10311 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010312 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010313}
10314
10315sub isLeafClass($$)
10316{
10317 my ($ClassId, $LibVersion) = @_;
10318 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10319}
10320
10321sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010322{ # check structured type for public fields
10323 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010324}
10325
10326sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010327{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010328 my ($TypePtr, $Skip, $Start, $End) = @_;
10329 return 0 if(not $TypePtr);
10330 if($End==-1) {
10331 $End = keys(%{$TypePtr->{"Memb"}})-1;
10332 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010333 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010334 {
10335 if($Skip and $Skip->{$MemPos})
10336 { # skip removed/added fields
10337 next;
10338 }
10339 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10340 {
10341 if(isPublic($TypePtr, $MemPos)) {
10342 return ($MemPos+1);
10343 }
10344 }
10345 }
10346 return 0;
10347}
10348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010349sub isReserved($)
10350{ # reserved fields == private
10351 my $MName = $_[0];
10352 if($MName=~/reserved|padding|f_spare/i) {
10353 return 1;
10354 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010355 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010356 return 1;
10357 }
10358 if($MName=~/(pad\d+)/i) {
10359 return 1;
10360 }
10361 return 0;
10362}
10363
10364sub isPublic($$)
10365{
10366 my ($TypePtr, $FieldPos) = @_;
10367 return 0 if(not $TypePtr);
10368 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10369 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10370 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10371 { # by name in C language
10372 # FIXME: add other methods to detect private members
10373 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10374 if($MName=~/priv|abidata|parent_object/i)
10375 { # C-styled private data
10376 return 0;
10377 }
10378 if(lc($MName) eq "abi")
10379 { # ABI information/reserved field
10380 return 0;
10381 }
10382 if(isReserved($MName))
10383 { # reserved fields
10384 return 0;
10385 }
10386 return 1;
10387 }
10388 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10389 { # by access in C++ language
10390 return 1;
10391 }
10392 return 0;
10393}
10394
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010395sub getVTable_Real($$)
10396{
10397 my ($ClassName, $LibVersion) = @_;
10398 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10399 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010400 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010401 if(defined $Type{"VTable"}) {
10402 return %{$Type{"VTable"}};
10403 }
10404 }
10405 return ();
10406}
10407
10408sub cmpVTables($)
10409{
10410 my $ClassName = $_[0];
10411 my $Res = cmpVTables_Real($ClassName, 1);
10412 if($Res==-1) {
10413 $Res = cmpVTables_Model($ClassName);
10414 }
10415 return $Res;
10416}
10417
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010418sub cmpVTables_Model($)
10419{
10420 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010421 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010422 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010423 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010424 return 1;
10425 }
10426 }
10427 return 0;
10428}
10429
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010430sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010431{
10432 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10434 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010435 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010436 my %VTable_Old = getVTable_Real($ClassName, 1);
10437 my %VTable_New = getVTable_Real($ClassName, 2);
10438 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010439 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010440 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010441 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010442 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10444 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010445 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010446 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010447 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010449 my $Entry1 = $VTable_Old{$Offset};
10450 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010451 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010452 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010454 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010455
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010456 $Entry1 = simpleVEntry($Entry1);
10457 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010458
10459 if($Entry1=~/ 0x/ and $Entry2=~/ 0x/)
10460 { # NOTE: problem with vtable-dumper
10461 next;
10462 }
10463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010464 if($Entry1 ne $Entry2)
10465 { # register as changed
10466 if($Entry1=~/::([^:]+)\Z/)
10467 {
10468 my $M1 = $1;
10469 if($Entry2=~/::([^:]+)\Z/)
10470 {
10471 my $M2 = $1;
10472 if($M1 eq $M2)
10473 { # overridden
10474 next;
10475 }
10476 }
10477 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010478 if(differentDumps("G"))
10479 {
10480 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10481 {
10482 # GCC 4.6.1: -0x00000000000000010
10483 # GCC 4.7.0: -16
10484 next;
10485 }
10486 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488 }
10489 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010491}
10492
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010493sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010494{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010495 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10497 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010498 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010499 { # already registered
10500 next;
10501 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010503 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010504 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 foreach my $Symbol (@Affected)
10506 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010507 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010508 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010509 "Target"=>$ClassName);
10510 }
10511 }
10512 }
10513}
10514
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010515sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010516{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010517 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010519 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010522 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010523 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010524 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010525 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 if($TName_Tid{1}{$ClassName}
10527 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010528 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010529 if(defined $CompleteSignature{1}{$Symbol}
10530 and $CompleteSignature{1}{$Symbol}{"Virt"})
10531 { # override some method in v.1
10532 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010533 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010534 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010535 }
10536 }
10537 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010538 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010539 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010540 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010541 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010542 if($TName_Tid{2}{$ClassName}
10543 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010544 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010545 if(defined $CompleteSignature{2}{$Symbol}
10546 and $CompleteSignature{2}{$Symbol}{"Virt"})
10547 { # override some method in v.2
10548 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010549 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010550 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551 }
10552 }
10553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010554 if($Level eq "Binary")
10555 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010556 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010557 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10558 { # check replacements, including pure virtual methods
10559 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10560 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010562 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10563 if($AddedPos==$RemovedPos)
10564 {
10565 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10566 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10567 last; # other methods will be reported as "added" or "removed"
10568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010570 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10571 {
10572 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10573 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 next;
10575 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010576 my $ProblemType = "Virtual_Replacement";
10577 my @Affected = ($RemovedVFunc);
10578 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10579 { # pure methods
10580 if(not isUsedClass($ClassId, 1, $Level))
10581 { # not a parameter of some exported method
10582 next;
10583 }
10584 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010585
10586 # affected all methods (both virtual and non-virtual ones)
10587 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10588 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010590 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010591 foreach my $AffectedInt (@Affected)
10592 {
10593 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10594 { # affected exported methods only
10595 next;
10596 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010597 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10598 next;
10599 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010600 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10601 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010602 "Target"=>get_Signature($AddedVFunc, 2),
10603 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010605 }
10606 }
10607 }
10608 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010609 if(not checkDump(1, "2.0")
10610 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010611 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010612 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010613 return;
10614 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010615 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010616 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010617 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 next if(not $ClassId_Old);
10619 if(not isCreatable($ClassId_Old, 1))
10620 { # skip classes without public constructors (including auto-generated)
10621 # example: class has only a private exported or private inline constructor
10622 next;
10623 }
10624 if($ClassName=~/>/)
10625 { # skip affected template instances
10626 next;
10627 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010628 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010630 if(not $ClassId_New) {
10631 next;
10632 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010633 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010634 if($Class_New{"Type"}!~/Class|Struct/)
10635 { # became typedef
10636 if($Level eq "Binary") {
10637 next;
10638 }
10639 if($Level eq "Source")
10640 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010641 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010642 if($Class_New{"Type"}!~/Class|Struct/) {
10643 next;
10644 }
10645 $ClassId_New = $Class_New{"Tid"};
10646 }
10647 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010648
10649 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10650 { # incomplete info in the ABI dump
10651 next;
10652 }
10653
10654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010655 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10656 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 +040010657
10658 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10659 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10660
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010661 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010662 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10663 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010664 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10665 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010666 my $Shift_Old = getShift($ClassId_Old, 1);
10667 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010668 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010669 my ($Added, $Removed) = (0, 0);
10670 my @StableBases_Old = ();
10671 foreach my $BaseId (@Bases_Old)
10672 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010673 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010674 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010675 push(@StableBases_Old, $BaseId);
10676 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010677 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010678 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 { # removed base
10680 # excluding namespace::SomeClass to SomeClass renaming
10681 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010682 if($Level eq "Binary")
10683 { # Binary-level
10684 if($Shift_Old ne $Shift_New)
10685 { # affected fields
10686 if(havePubFields(\%Class_Old)) {
10687 $ProblemKind .= "_And_Shift";
10688 }
10689 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10690 $ProblemKind .= "_And_Size";
10691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10694 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010695 { # affected v-table
10696 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010697 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010698 }
10699 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010700 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010701 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10702 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010703 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10704 {
10705 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10706 if($ProblemKind=~/VTable/) {
10707 $VTableChanged_M{$SubName}=1;
10708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010709 }
10710 }
10711 foreach my $Interface (@Affected)
10712 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010713 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10714 next;
10715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010716 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010717 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010718 "Target"=>$BaseName,
10719 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10720 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10721 "Shift"=>abs($Shift_New-$Shift_Old) );
10722 }
10723 $Removed+=1;
10724 }
10725 }
10726 my @StableBases_New = ();
10727 foreach my $BaseId (@Bases_New)
10728 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010729 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010730 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010731 push(@StableBases_New, $BaseId);
10732 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010733 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010734 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 { # added base
10736 # excluding namespace::SomeClass to SomeClass renaming
10737 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010738 if($Level eq "Binary")
10739 { # Binary-level
10740 if($Shift_Old ne $Shift_New)
10741 { # affected fields
10742 if(havePubFields(\%Class_Old)) {
10743 $ProblemKind .= "_And_Shift";
10744 }
10745 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10746 $ProblemKind .= "_And_Size";
10747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010749 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10750 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010751 { # affected v-table
10752 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010753 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 }
10755 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010756 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010757 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10758 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010759 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10760 {
10761 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10762 if($ProblemKind=~/VTable/) {
10763 $VTableChanged_M{$SubName}=1;
10764 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010765 }
10766 }
10767 foreach my $Interface (@Affected)
10768 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010769 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10770 next;
10771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010772 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010774 "Target"=>$BaseName,
10775 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10776 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10777 "Shift"=>abs($Shift_New-$Shift_Old) );
10778 }
10779 $Added+=1;
10780 }
10781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010782 if($Level eq "Binary")
10783 { # Binary-level
10784 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010785 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10786 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010787 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010788 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010789 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010790 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010791 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010792 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10793 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010794 if($NewPos!=$OldPos)
10795 { # changed position of the base class
10796 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010797 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010798 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10799 next;
10800 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010801 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10802 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010803 "Target"=>$BaseName,
10804 "Old_Value"=>$OldPos-1,
10805 "New_Value"=>$NewPos-1 );
10806 }
10807 }
10808 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10809 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10810 { # became non-virtual base
10811 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10812 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010813 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10814 next;
10815 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010816 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10817 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010818 "Target"=>$BaseName );
10819 }
10820 }
10821 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10822 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10823 { # became virtual base
10824 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10825 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010826 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10827 next;
10828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010829 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10830 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010831 "Target"=>$BaseName );
10832 }
10833 }
10834 }
10835 }
10836 # detect size changes in base classes
10837 if($Shift_Old!=$Shift_New)
10838 { # size of allocable class
10839 foreach my $BaseId (@StableBases_Old)
10840 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010841 my %BaseType = get_Type($BaseId, 1);
10842 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010843 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010844 if($Size_Old ne $Size_New
10845 and $Size_Old and $Size_New)
10846 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010847 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010848 if(isCopyingClass($BaseId, 1)) {
10849 $ProblemType = "Size_Of_Copying_Class";
10850 }
10851 elsif($AllocableClass{1}{$BaseType{"Name"}})
10852 {
10853 if($Size_New>$Size_Old)
10854 { # increased size
10855 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010857 else
10858 { # decreased size
10859 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10860 if(not havePubFields(\%Class_Old))
10861 { # affected class has no public members
10862 next;
10863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010865 }
10866 next if(not $ProblemType);
10867 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10868 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010869 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10870 next;
10871 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010872 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10873 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 "Target"=>$BaseType{"Name"},
10875 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10876 "New_Size"=>$Size_New*$BYTE_SIZE );
10877 }
10878 }
10879 }
10880 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010881 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010882 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010883 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010884 { # compare virtual tables size in base classes
10885 my $VShift_Old = getVShift($ClassId_Old, 1);
10886 my $VShift_New = getVShift($ClassId_New, 2);
10887 if($VShift_Old ne $VShift_New)
10888 { # changes in the base class or changes in the list of base classes
10889 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10890 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10891 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010892 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010893 foreach my $BaseId (@AllBases_Old)
10894 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010895 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010896 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 { # lost base
10898 next;
10899 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010900 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10901 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010902 if($VSize_Old!=$VSize_New)
10903 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010904 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010905 { # TODO: affected non-virtual methods?
10906 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010907 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10908 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010909 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010910 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010911 { # skip interfaces that have not changed the absolute virtual position
10912 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010913 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010914 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10915 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010916 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010917 $VTableChanged_M{$BaseType{"Name"}} = 1;
10918 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010919 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10920 { # the reason of the layout change: added virtual functions
10921 next if($VirtualReplacement{$VirtFunc});
10922 my $ProblemType = "Added_Virtual_Method";
10923 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10924 $ProblemType = "Added_Pure_Virtual_Method";
10925 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010926 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010927 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 "Target"=>get_Signature($VirtFunc, 2) );
10929 }
10930 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10931 { # the reason of the layout change: removed virtual functions
10932 next if($VirtualReplacement{$VirtFunc});
10933 my $ProblemType = "Removed_Virtual_Method";
10934 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10935 $ProblemType = "Removed_Pure_Virtual_Method";
10936 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010937 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010938 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010939 "Target"=>get_Signature($VirtFunc, 1) );
10940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010941 }
10942 }
10943 }
10944 }
10945 }
10946 }
10947 }
10948}
10949
10950sub isCreatable($$)
10951{
10952 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010953 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010954 or isCopyingClass($ClassId, $LibVersion)) {
10955 return 1;
10956 }
10957 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10958 { # Fix for incomplete data: if this class has
10959 # a base class then it should also has a constructor
10960 return 1;
10961 }
10962 if($ReturnedClass{$LibVersion}{$ClassId})
10963 { # returned by some method of this class
10964 # or any other class
10965 return 1;
10966 }
10967 return 0;
10968}
10969
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010970sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010971{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010972 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010973 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10974 { # parameter of some exported method
10975 return 1;
10976 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010977 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10978 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010979 { # method from target class
10980 return 1;
10981 }
10982 return 0;
10983}
10984
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010985sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010986{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010988 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010989 # - virtual
10990 # - pure-virtual
10991 # - non-virtual
10992 if($CompleteSignature{1}{$Interface}{"Data"})
10993 { # global data is not affected
10994 return;
10995 }
10996 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010997 if(not $Class_Id) {
10998 return;
10999 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011000 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011001 if(cmpVTables_Real($CName, 1)==0)
11002 { # no changes
11003 return;
11004 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011005 $CheckedTypes{$Level}{$CName} = 1;
11006 if($Level eq "Binary")
11007 { # Binary-level
11008 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11009 and not isUsedClass($Class_Id, 1, $Level))
11010 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011011 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011012 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011013 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011014 }
11015 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11016 {
11017 if(defined $VirtualTable{2}{$CName}{$Func}
11018 and defined $CompleteSignature{2}{$Func})
11019 {
11020 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11021 and $CompleteSignature{2}{$Func}{"PureVirt"})
11022 { # became pure virtual
11023 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11024 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011025 "Target"=>get_Signature_M($Func, 1) );
11026 $VTableChanged_M{$CName} = 1;
11027 }
11028 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11029 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11030 { # became non-pure virtual
11031 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11032 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011033 "Target"=>get_Signature_M($Func, 1) );
11034 $VTableChanged_M{$CName} = 1;
11035 }
11036 }
11037 }
11038 if($Level eq "Binary")
11039 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011040 # check virtual table structure
11041 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11042 {
11043 next if($Interface eq $AddedVFunc);
11044 next if($VirtualReplacement{$AddedVFunc});
11045 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11046 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11047 { # pure virtual methods affect all others (virtual and non-virtual)
11048 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011049 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011050 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011051 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011052 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011053 elsif(not defined $VirtualTable{1}{$CName}
11054 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011056 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011057 { # became polymorphous class, added v-table pointer
11058 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011060 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011061 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011062 }
11063 else
11064 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011065 my $VSize_Old = getVTable_Size($CName, 1);
11066 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011067 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011068 if(isCopyingClass($Class_Id, 1))
11069 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11070 my $ProblemType = "Added_Virtual_Method";
11071 if(isLeafClass($Class_Id, 1)) {
11072 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11073 }
11074 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11075 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011076 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011077 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011079 else
11080 {
11081 my $ProblemType = "Added_Virtual_Method";
11082 if(isLeafClass($Class_Id, 1)) {
11083 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11084 }
11085 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11086 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011087 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011088 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011090 }
11091 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011092 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11093 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011094 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011095 if(defined $VirtualTable{1}{$CName}
11096 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011097 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011098 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11099 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011100
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011101 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011102 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011103 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11104 foreach my $ASymbol (@Affected)
11105 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011106 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11107 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011108 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011109 next;
11110 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011111 }
11112 $CheckedSymbols{$Level}{$ASymbol} = 1;
11113 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11114 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011115 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011116 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011118 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119 }
11120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011121 else {
11122 # safe
11123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011124 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011125 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11126 {
11127 next if($VirtualReplacement{$RemovedVFunc});
11128 if($RemovedVFunc eq $Interface
11129 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11130 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011131 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011132 next;
11133 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011134 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 { # became non-polymorphous class, removed v-table pointer
11136 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11137 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011138 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011139 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011140 }
11141 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11142 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11143 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011144 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011146 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11147 next;
11148 }
11149 my $VPos_New = -1;
11150 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011152 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11153 }
11154 else
11155 {
11156 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011157 next;
11158 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011159 }
11160 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11161 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11162 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11163 {
11164 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11165 foreach my $ASymbol (@Affected)
11166 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011167 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11168 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011169 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011170 next;
11171 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011172 }
11173 my $ProblemType = "Removed_Virtual_Method";
11174 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11175 $ProblemType = "Removed_Pure_Virtual_Method";
11176 }
11177 $CheckedSymbols{$Level}{$ASymbol} = 1;
11178 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11179 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011180 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011181 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011183 }
11184 }
11185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011186 }
11187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011188 else
11189 { # Source-level
11190 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011191 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011192 next if($Interface eq $AddedVFunc);
11193 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011194 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011195 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11196 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 "Target"=>get_Signature($AddedVFunc, 2) );
11198 }
11199 }
11200 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11201 {
11202 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11203 {
11204 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11205 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011206 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011207 }
11208 }
11209 }
11210}
11211
11212sub find_MemberPair_Pos_byName($$)
11213{
11214 my ($Member_Name, $Pair_Type) = @_;
11215 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11216 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11217 {
11218 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11219 {
11220 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11221 $Name=~s/\A[_]+|[_]+\Z//g;
11222 if($Name eq $Member_Name) {
11223 return $MemberPair_Pos;
11224 }
11225 }
11226 }
11227 return "lost";
11228}
11229
11230sub find_MemberPair_Pos_byVal($$)
11231{
11232 my ($Member_Value, $Pair_Type) = @_;
11233 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11234 {
11235 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11236 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11237 return $MemberPair_Pos;
11238 }
11239 }
11240 return "lost";
11241}
11242
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011243sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011245 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011246 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011247 if( $_->{"T1"} eq $_[0]
11248 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011249 {
11250 return 1;
11251 }
11252 }
11253 return 0;
11254}
11255
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011256sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011257{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011258 my %IDs = (
11259 "T1" => $_[0],
11260 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011261 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011262 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011263}
11264
11265sub isRenamed($$$$$)
11266{
11267 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11268 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11269 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011270 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011271 if(not defined $Type2->{"Memb"}{$MemPos}) {
11272 return "";
11273 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011275 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011277 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11278 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011279 if($MemberPair_Pos_Rev eq "lost")
11280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011281 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11282 { # base type match
11283 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011285 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11286 { # exact type match
11287 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011288 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011289 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11290 { # size match
11291 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011292 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011293 if(isReserved($Pair_Name))
11294 { # reserved fields
11295 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011296 }
11297 }
11298 return "";
11299}
11300
11301sub isLastElem($$)
11302{
11303 my ($Pos, $TypeRef) = @_;
11304 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11305 if($Name=~/last|count|max|total/i)
11306 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11307 return 1;
11308 }
11309 elsif($Name=~/END|NLIMITS\Z/)
11310 { # __RLIMIT_NLIMITS
11311 return 1;
11312 }
11313 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11314 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11315 { # NImageFormats, NColorRoles
11316 return 1;
11317 }
11318 return 0;
11319}
11320
11321sub nonComparable($$)
11322{
11323 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011324
11325 my $N1 = $T1->{"Name"};
11326 my $N2 = $T2->{"Name"};
11327
11328 $N1=~s/\A(struct|union|enum) //;
11329 $N2=~s/\A(struct|union|enum) //;
11330
11331 if($N1 ne $N2
11332 and not isAnon($N1)
11333 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011334 { # different names
11335 if($T1->{"Type"} ne "Pointer"
11336 or $T2->{"Type"} ne "Pointer")
11337 { # compare base types
11338 return 1;
11339 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011340 if($N1!~/\Avoid\s*\*/
11341 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011342 {
11343 return 1;
11344 }
11345 }
11346 elsif($T1->{"Type"} ne $T2->{"Type"})
11347 { # different types
11348 if($T1->{"Type"} eq "Class"
11349 and $T2->{"Type"} eq "Struct")
11350 { # "class" to "struct"
11351 return 0;
11352 }
11353 elsif($T2->{"Type"} eq "Class"
11354 and $T1->{"Type"} eq "Struct")
11355 { # "struct" to "class"
11356 return 0;
11357 }
11358 else
11359 { # "class" to "enum"
11360 # "union" to "class"
11361 # ...
11362 return 1;
11363 }
11364 }
11365 return 0;
11366}
11367
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011368sub isOpaque($)
11369{
11370 my $T = $_[0];
11371 if(not defined $T->{"Memb"})
11372 {
11373 return 1;
11374 }
11375 return 0;
11376}
11377
11378sub removeVPtr($)
11379{ # support for old ABI dumps
11380 my $TPtr = $_[0];
11381 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11382 if($#Pos>=1)
11383 {
11384 foreach my $Pos (0 .. $#Pos-1)
11385 {
11386 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11387 }
11388 delete($TPtr->{"Memb"}{$#Pos});
11389 }
11390}
11391
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011392sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011393{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011394 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011395 return {} if(not $Type1_Id or not $Type2_Id);
11396
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011397 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011398 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011399 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011400 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011401
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011402 my %Type1 = get_Type($Type1_Id, 1);
11403 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011404 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011405 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011406 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011407
11408 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011409 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11410 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011411
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011412 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11413
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011414 my %SubProblems = ();
11415
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011416 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11417 {
11418 if($Type1_Pure{"Type"}=~/Struct|Union/
11419 and $Type2_Pure{"Type"}=~/Struct|Union/)
11420 {
11421 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11422 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011423 if(not defined $UsedDump{1}{"DWARF"}
11424 and not defined $UsedDump{2}{"DWARF"})
11425 {
11426 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11427 "Target"=>$Type1_Pure{"Name"},
11428 "Type_Name"=>$Type1_Pure{"Name"} );
11429 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011430
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011431 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011432 }
11433 }
11434 }
11435
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011436 if(not $Type1_Pure{"Size"}
11437 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011438 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011439 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11440 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11441 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011442 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011443 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011444 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011445 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011447 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011448 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011449 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11450 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11451 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011452
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011453 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11454 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011455 }
11456
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011457 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11458 { # support for old ABI dumps
11459 # _vptr field added in 3.0
11460 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11461 {
11462 if(defined $Type2_Pure{"Memb"}
11463 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11464 {
11465 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11466 delete($Type2_Pure{"Memb"}{0});
11467 }
11468 else {
11469 removeVPtr(\%Type2_Pure);
11470 }
11471 }
11472 }
11473 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11474 {
11475 if(defined $Type1_Pure{"Memb"}
11476 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11477 {
11478 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11479 delete($Type1_Pure{"Memb"}{0});
11480 }
11481 else {
11482 removeVPtr(\%Type1_Pure);
11483 }
11484 }
11485 }
11486 }
11487
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011488 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11489 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011490
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011491 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011492 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11493 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011494 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011495 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11496 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011497 if($Base_1{"Name"} ne $Base_2{"Name"})
11498 {
11499 if(differentDumps("G")
11500 or differentDumps("V"))
11501 { # different GCC versions or different dumps
11502 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11503 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11504 # std::__va_list and __va_list
11505 $Base_1{"Name"}=~s/\A(\w+::)+//;
11506 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011507 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11508 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011510 }
11511 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11512 and $Base_1{"Name"} ne $Base_2{"Name"})
11513 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011514 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011515 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011516 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011517 {
11518 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11519 "Target"=>$Typedef_1{"Name"},
11520 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011521 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11522 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11523 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011524 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11525 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011526 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011527 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011528 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11529 {
11530 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11531 "Target"=>$Typedef_1{"Name"},
11532 "Type_Name"=>$Typedef_1{"Name"},
11533 "Old_Value"=>$Base_1{"Name"},
11534 "New_Value"=>$Base_2{"Name"} );
11535 }
11536 else
11537 {
11538 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11539 "Target"=>$Typedef_1{"Name"},
11540 "Type_Name"=>$Typedef_1{"Name"},
11541 "Old_Value"=>$Base_1{"Name"},
11542 "New_Value"=>$Base_2{"Name"} );
11543 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011544 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011545 }
11546 }
11547 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11548 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011549 my $TT1 = $Type1_Pure{"Type"};
11550 my $TT2 = $Type2_Pure{"Type"};
11551
11552 if($TT1 ne $TT2
11553 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011554 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011555 my $Short1 = $Type1_Pure{"Name"};
11556 my $Short2 = $Type2_Pure{"Name"};
11557
11558 $Short1=~s/\A\Q$TT1\E //ig;
11559 $Short2=~s/\A\Q$TT2\E //ig;
11560
11561 if($Short1 eq $Short2)
11562 {
11563 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11564 "Target"=>$Type1_Pure{"Name"},
11565 "Type_Name"=>$Type1_Pure{"Name"},
11566 "Old_Value"=>lc($Type1_Pure{"Type"}),
11567 "New_Value"=>lc($Type2_Pure{"Type"}) );
11568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011569 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011570 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011571 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011572 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11574 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11575 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11576 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011577 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011578 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011579 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011580 {
11581 my $ProblemKind = "DataType_Size";
11582 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011583 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011584 {
11585 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11586 $ProblemKind = "Size_Of_Copying_Class";
11587 }
11588 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11589 {
11590 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11591 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11592 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011593 else
11594 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011595 # descreased size of allocable class
11596 # it has no special effects
11597 }
11598 }
11599 }
11600 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11601 "Target"=>$Type1_Pure{"Name"},
11602 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011603 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011604 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011605 }
11606 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011607 if(defined $Type1_Pure{"BaseType"}
11608 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011609 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011610 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11611 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011612 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011613 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11614 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011615 }
11616 }
11617 }
11618 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11619 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11620 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11621 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11622 { # detect removed and renamed fields
11623 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11624 next if(not $Member_Name);
11625 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);
11626 if($MemberPair_Pos eq "lost")
11627 {
11628 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11629 {
11630 if(isUnnamed($Member_Name))
11631 { # support for old-version dumps
11632 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011633 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 next;
11635 }
11636 }
11637 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11638 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011639 $RenamedField{$Member_Pos} = $RenamedTo;
11640 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011641 }
11642 else
11643 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011644 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 }
11646 }
11647 elsif($Type1_Pure{"Type"} eq "Enum")
11648 {
11649 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11650 next if($Member_Value1 eq "");
11651 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11652 if($MemberPair_Pos ne "lost")
11653 { # renamed
11654 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11655 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11656 if($MemberPair_Pos_Rev eq "lost")
11657 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011658 $RenamedField{$Member_Pos} = $RenamedTo;
11659 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011660 }
11661 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011662 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 }
11664 }
11665 else
11666 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011667 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011668 }
11669 }
11670 }
11671 else
11672 { # related
11673 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11674 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11675 }
11676 }
11677 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11678 { # detect added fields
11679 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11680 next if(not $Member_Name);
11681 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);
11682 if($MemberPair_Pos eq "lost")
11683 {
11684 if(isUnnamed($Member_Name))
11685 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011686 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011687 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011688 next;
11689 }
11690 }
11691 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11692 {
11693 if(not $RenamedField_Rev{$Member_Pos})
11694 { # added
11695 $AddedField{$Member_Pos}=1;
11696 }
11697 }
11698 }
11699 }
11700 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11701 { # detect moved fields
11702 my (%RelPos, %RelPosName, %AbsPos) = ();
11703 my $Pos = 0;
11704 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11705 { # relative positions in 1st version
11706 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11707 next if(not $Member_Name);
11708 if(not $RemovedField{$Member_Pos})
11709 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011710 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011711 $RelPosName{1}{$Pos} = $Member_Name;
11712 $AbsPos{1}{$Pos++} = $Member_Pos;
11713 }
11714 }
11715 $Pos = 0;
11716 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11717 { # relative positions in 2nd version
11718 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11719 next if(not $Member_Name);
11720 if(not $AddedField{$Member_Pos})
11721 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011722 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011723 $RelPosName{2}{$Pos} = $Member_Name;
11724 $AbsPos{2}{$Pos++} = $Member_Pos;
11725 }
11726 }
11727 foreach my $Member_Name (keys(%{$RelPos{1}}))
11728 {
11729 my $RPos1 = $RelPos{1}{$Member_Name};
11730 my $AbsPos1 = $NameToPosA{$Member_Name};
11731 my $Member_Name2 = $Member_Name;
11732 if(my $RenamedTo = $RenamedField{$AbsPos1})
11733 { # renamed
11734 $Member_Name2 = $RenamedTo;
11735 }
11736 my $RPos2 = $RelPos{2}{$Member_Name2};
11737 if($RPos2 ne "" and $RPos1 ne $RPos2)
11738 { # different relative positions
11739 my $AbsPos2 = $NameToPosB{$Member_Name2};
11740 if($AbsPos1 ne $AbsPos2)
11741 { # different absolute positions
11742 my $ProblemType = "Moved_Field";
11743 if(not isPublic(\%Type1_Pure, $AbsPos1))
11744 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011745 if($Level eq "Source") {
11746 next;
11747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011748 $ProblemType = "Moved_Private_Field";
11749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011750 if($Level eq "Binary"
11751 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011752 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011753 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011755 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011756 if($MemSize1 ne $MemSize2) {
11757 $ProblemType .= "_And_Size";
11758 }
11759 }
11760 if($ProblemType eq "Moved_Private_Field") {
11761 next;
11762 }
11763 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11764 "Target"=>$Member_Name,
11765 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 "Old_Value"=>$RPos1,
11767 "New_Value"=>$RPos2 );
11768 }
11769 }
11770 }
11771 }
11772 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011773 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011774 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11775 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011776 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011777 if(my $RenamedTo = $RenamedField{$Member_Pos})
11778 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011779 if(defined $Constants{2}{$Member_Name})
11780 {
11781 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11782 { # define OLD NEW
11783 next; # Safe
11784 }
11785 }
11786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011787 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11788 {
11789 if(isPublic(\%Type1_Pure, $Member_Pos))
11790 {
11791 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11792 "Target"=>$Member_Name,
11793 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011794 "Old_Value"=>$Member_Name,
11795 "New_Value"=>$RenamedTo );
11796 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011797 elsif(isReserved($Member_Name))
11798 {
11799 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11800 "Target"=>$Member_Name,
11801 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011802 "Old_Value"=>$Member_Name,
11803 "New_Value"=>$RenamedTo );
11804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011805 }
11806 elsif($Type1_Pure{"Type"} eq "Enum")
11807 {
11808 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11809 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11810 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011811 "Old_Value"=>$Member_Name,
11812 "New_Value"=>$RenamedTo );
11813 }
11814 }
11815 elsif($RemovedField{$Member_Pos})
11816 { # removed
11817 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11818 {
11819 my $ProblemType = "Removed_Field";
11820 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011821 or isUnnamed($Member_Name))
11822 {
11823 if($Level eq "Source") {
11824 next;
11825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011826 $ProblemType = "Removed_Private_Field";
11827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011828 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011829 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011830 {
11831 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11832 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011833 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 +040011834 { # changed offset
11835 $ProblemType .= "_And_Layout";
11836 }
11837 }
11838 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11839 { # affected size
11840 $ProblemType .= "_And_Size";
11841 }
11842 }
11843 if($ProblemType eq "Removed_Private_Field") {
11844 next;
11845 }
11846 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11847 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011848 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011849 }
11850 elsif($Type2_Pure{"Type"} eq "Union")
11851 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011852 if($Level eq "Binary"
11853 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011854 {
11855 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11856 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011857 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011858 }
11859 else
11860 {
11861 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11862 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011863 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011864 }
11865 }
11866 elsif($Type1_Pure{"Type"} eq "Enum")
11867 {
11868 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11869 "Target"=>$Member_Name,
11870 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011871 "Old_Value"=>$Member_Name );
11872 }
11873 }
11874 else
11875 { # changed
11876 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11877 if($Type1_Pure{"Type"} eq "Enum")
11878 {
11879 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11880 next if($Member_Value1 eq "");
11881 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11882 next if($Member_Value2 eq "");
11883 if($Member_Value1 ne $Member_Value2)
11884 {
11885 my $ProblemType = "Enum_Member_Value";
11886 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11887 $ProblemType = "Enum_Last_Member_Value";
11888 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011889 if($SkipConstants{1}{$Member_Name}) {
11890 $ProblemType = "Enum_Private_Member_Value";
11891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011892 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11893 "Target"=>$Member_Name,
11894 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011895 "Old_Value"=>$Member_Value1,
11896 "New_Value"=>$Member_Value2 );
11897 }
11898 }
11899 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11900 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011901 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11902 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11903
11904 if($Access1 ne "private"
11905 and $Access2 eq "private")
11906 {
11907 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11908 "Target"=>$Member_Name,
11909 "Type_Name"=>$Type1_Pure{"Name"});
11910 }
11911 elsif($Access1 ne "protected"
11912 and $Access1 ne "private"
11913 and $Access2 eq "protected")
11914 {
11915 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11916 "Target"=>$Member_Name,
11917 "Type_Name"=>$Type1_Pure{"Name"});
11918 }
11919
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011920 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11921 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011922 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011923 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11924 $SizeV1 = $BSize1;
11925 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011926 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011927 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11928 $SizeV2 = $BSize2;
11929 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011930 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11931 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011932 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011933 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011934 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011935 {
11936 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11937 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11938 { # field size change (including anon-structures and unions)
11939 # - same types
11940 # - unnamed types
11941 # - bitfields
11942 my $ProblemType = "Field_Size";
11943 if(not isPublic(\%Type1_Pure, $Member_Pos)
11944 or isUnnamed($Member_Name))
11945 { # should not be accessed by applications, goes to "Low Severity"
11946 # example: "abidata" members in GStreamer types
11947 $ProblemType = "Private_".$ProblemType;
11948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011949 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 +040011950 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011951 if($Type2_Pure{"Type"} ne "Union"
11952 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011954 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 +040011955 { # changed offset
11956 $ProblemType .= "_And_Layout";
11957 }
11958 }
11959 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11960 $ProblemType .= "_And_Type_Size";
11961 }
11962 }
11963 if($ProblemType eq "Private_Field_Size")
11964 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011965 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011966 if($ProblemType eq "Field_Size")
11967 {
11968 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11969 { # Low severity
11970 $ProblemType = "Struct_Field_Size_Increased";
11971 }
11972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011973 if($ProblemType)
11974 { # register a problem
11975 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11976 "Target"=>$Member_Name,
11977 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011978 "Old_Size"=>$SizeV1,
11979 "New_Size"=>$SizeV2);
11980 }
11981 }
11982 }
11983 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11984 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11985 { # do NOT check bitfield type changes
11986 next;
11987 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011988 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011989 {
11990 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11991 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11992 {
11993 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11994 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011995 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011996 }
11997 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11998 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11999 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012000 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012001 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012002 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012003 }
12004 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012005 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12006 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012007 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012008 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12009 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012010
12011 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012012 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012013 or $ProblemType eq "Field_Type_And_Size"
12014 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012016 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012017 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012018 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012019 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012020 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012021 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012022 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012023 }
12024 }
12025 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12026 {
12027 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012028 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012029 }
12030 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012031 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012032 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012033 }
12034 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12035 {
12036 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012037 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012038 }
12039 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012040 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012042 }
12043 }
12044 }
12045
12046 if($Level eq "Source")
12047 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012048 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012049 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012050 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12051 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012052
12053 if($ProblemType eq "Field_Type")
12054 {
12055 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012056 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 }
12058 }
12059 }
12060 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012061
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012062 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 {
12064 my $ProblemType_Init = $ProblemType;
12065 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012066 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012067 if(not isPublic(\%Type1_Pure, $Member_Pos)
12068 or isUnnamed($Member_Name)) {
12069 $ProblemType = "Private_".$ProblemType;
12070 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012071 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 +040012072 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012073 if($Type2_Pure{"Type"} ne "Union"
12074 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012075 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012076 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 +040012077 { # changed offset
12078 $ProblemType .= "_And_Layout";
12079 }
12080 }
12081 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12082 $ProblemType .= "_And_Type_Size";
12083 }
12084 }
12085 }
12086 else
12087 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012088 # TODO: Private_Field_Type rule?
12089
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012090 if(not isPublic(\%Type1_Pure, $Member_Pos)
12091 or isUnnamed($Member_Name)) {
12092 next;
12093 }
12094 }
12095 if($ProblemType eq "Private_Field_Type_And_Size")
12096 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012097 }
12098 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12099 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012100 "Type_Name"=>$Type1_Pure{"Name"});
12101
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012102 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012103 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012104 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012105 }
12106 }
12107 if(not isPublic(\%Type1_Pure, $Member_Pos))
12108 { # do NOT check internal type changes
12109 next;
12110 }
12111 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012112 { # checking member type changes
12113 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12114
12115 my %DupProblems = ();
12116
12117 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012118 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012119 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012120 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012121 if(not defined $AllAffected)
12122 {
12123 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12124 next;
12125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012126 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012127
12128 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12129 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12130
12131 if(not defined $AllAffected)
12132 {
12133 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012134 }
12135 }
12136 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012137
12138 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012139 }
12140 }
12141 }
12142 }
12143 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12144 { # checking added members, public and private
12145 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12146 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012147 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012148 if($AddedField{$Member_Pos})
12149 { # added
12150 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12151 {
12152 my $ProblemType = "Added_Field";
12153 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012154 or isUnnamed($Member_Name))
12155 {
12156 if($Level eq "Source") {
12157 next;
12158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012159 $ProblemType = "Added_Private_Field";
12160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012161 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012162 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012163 {
12164 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12165 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012166 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 +040012167 { # changed offset
12168 $ProblemType .= "_And_Layout";
12169 }
12170 }
12171 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12172 $ProblemType .= "_And_Size";
12173 }
12174 }
12175 if($ProblemType eq "Added_Private_Field")
12176 { # skip added private fields
12177 next;
12178 }
12179 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12180 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012181 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012182 }
12183 elsif($Type2_Pure{"Type"} eq "Union")
12184 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012185 if($Level eq "Binary"
12186 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012187 {
12188 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12189 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012190 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012191 }
12192 else
12193 {
12194 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12195 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012196 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 }
12198 }
12199 elsif($Type2_Pure{"Type"} eq "Enum")
12200 {
12201 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12202 next if($Member_Value eq "");
12203 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12204 "Target"=>$Member_Name,
12205 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012206 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 }
12208 }
12209 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012212 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213}
12214
12215sub isUnnamed($) {
12216 return $_[0]=~/\Aunnamed\d+\Z/;
12217}
12218
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012219sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012220{
12221 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012222 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12223 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12224 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12225 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012226 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012227 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012228 }
12229 return $TypeName;
12230}
12231
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012232sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012234 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012235 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12237 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012239 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12240 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012241 return () if(not $Type{"Type"});
12242 if($Type{"Type"} ne $Type_Type)
12243 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012244 return () if(not $Type{"BaseType"});
12245 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012247 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 return %Type;
12249}
12250
12251my %TypeSpecAttributes = (
12252 "Const" => 1,
12253 "Volatile" => 1,
12254 "ConstVolatile" => 1,
12255 "Restrict" => 1,
12256 "Typedef" => 1
12257);
12258
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012259sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012261 my ($TypeId, $Info) = @_;
12262 if(not $TypeId or not $Info
12263 or not $Info->{$TypeId}) {
12264 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012265 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012266 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12267 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12268 }
12269 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012270 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012272 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012273 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012274 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 return %Type;
12276}
12277
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012278sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012279{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012280 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012282 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12283 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012285 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12286 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012287 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12288 my $PLevel = 0;
12289 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12290 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012292 return $PLevel if(not $Type{"BaseType"});
12293 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12294 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12295 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296}
12297
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012298sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012299{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012300 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012301 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012302 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12303 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012305 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12306 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012307 return %Type if(not $Type{"BaseType"});
12308 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012309 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012310 return %Type;
12311}
12312
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012313sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012315 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012316 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012317 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12318 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012319 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012320 my $Qual = "";
12321 if($Type{"Type"} eq "Pointer") {
12322 $Qual .= "*";
12323 }
12324 elsif($Type{"Type"} eq "Ref") {
12325 $Qual .= "&";
12326 }
12327 elsif($Type{"Type"} eq "ConstVolatile") {
12328 $Qual .= "const volatile";
12329 }
12330 elsif($Type{"Type"} eq "Const"
12331 or $Type{"Type"} eq "Volatile"
12332 or $Type{"Type"} eq "Restrict") {
12333 $Qual .= lc($Type{"Type"});
12334 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012335 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012336 return $BQual.$Qual;
12337}
12338
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012339sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012340{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012341 my ($TypeId, $Info) = @_;
12342 if(not $TypeId or not $Info
12343 or not $Info->{$TypeId}) {
12344 return ();
12345 }
12346 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012347 return %Type if(not $Type{"BaseType"});
12348 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012349 {
12350 if($Info->{$BTid}) {
12351 return %{$Info->{$BTid}};
12352 }
12353 else { # something is going wrong
12354 return ();
12355 }
12356 }
12357 else {
12358 return %Type;
12359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012360}
12361
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012362sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012363{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012364 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012365 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012366 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12367 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012368}
12369
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012370sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012371{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012372 my $Symbol = $_[0];
12373 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12374}
12375
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012376sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012377 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12378}
12379
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012380sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012382 my ($SInfo, $LibVersion) = @_;
12383
12384 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012385 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012386 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012388 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 return 1;
12390 }
12391 }
12392 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012393 if(my $ShortName = $SInfo->{"ShortName"})
12394 {
12395 if(index($ShortName,"<")!=-1
12396 and index($ShortName,">")!=-1) {
12397 return 1;
12398 }
12399 }
12400
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012401 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012402}
12403
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012404sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012405{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012406 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012407 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012408 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012409 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410 { # class specialization
12411 return 1;
12412 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012413 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012414 { # method specialization
12415 return 1;
12416 }
12417 }
12418 return 0;
12419}
12420
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012421sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012422{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012423 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012424
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012425 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426 { # non-public global data
12427 return 0;
12428 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012429
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012430 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012431 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012432 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012433 }
12434
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012435 if($Symbol=~/\A_Z/)
12436 {
12437 if($Symbol=~/[CD][3-4]E/) {
12438 return 0;
12439 }
12440 }
12441
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012442 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012443 { # support for old ABI dumps in --headers-only mode
12444 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12445 {
12446 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12447 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449 if(not $PType or $PType eq "Unknown") {
12450 return 0;
12451 }
12452 }
12453 }
12454 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012455 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012457 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12458
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012459 if($SkipSymbols{$LibVersion}{$Symbol})
12460 { # user defined symbols to ignore
12461 return 0;
12462 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012463
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012464 if($SymbolsListPath and not $SymbolsList{$Symbol})
12465 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012466 if(not $TargetHeadersPath or not $Header
12467 or not is_target_header($Header, 1))
12468 { # -symbols-list | -headers-list
12469 return 0;
12470 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012471 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012472
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012473 if($AppPath and not $SymbolsList_App{$Symbol})
12474 { # user defined symbols (in application)
12475 return 0;
12476 }
12477
12478 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12479
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012480 if($ClassId)
12481 {
12482 if(not isTargetType($ClassId, $LibVersion)) {
12483 return 0;
12484 }
12485 }
12486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012487 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12488 if(not $NameSpace and $ClassId)
12489 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012490 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012491 }
12492 if($NameSpace)
12493 { # user defined namespaces to ignore
12494 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12495 return 0;
12496 }
12497 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12498 { # nested namespaces
12499 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12500 return 0;
12501 }
12502 }
12503 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012504 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012506 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012507 { # --skip-headers or <skip_headers> (not <skip_including>)
12508 if($Skip==1) {
12509 return 0;
12510 }
12511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012512 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012513 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012514 { # user defined types
12515 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12516
12517 if(not $TypesList{$CName})
12518 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012519 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12520 {
12521 $CName=~s/\A\Q$NS\E\:\://g;
12522 }
12523
12524 if(not $TypesList{$CName})
12525 {
12526 my $Found = 0;
12527
12528 while($CName=~s/\:\:.+?\Z//)
12529 {
12530 if($TypesList{$CName})
12531 {
12532 $Found = 1;
12533 last;
12534 }
12535 }
12536
12537 if(not $Found) {
12538 return 0;
12539 }
12540 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012541 }
12542 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012543
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012544 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12545 { # non-target symbols
12546 return 0;
12547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012548 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012550 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12551 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012552 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012553 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12554 { # inline virtual methods
12555 if($Type=~/InlineVirt/) {
12556 return 1;
12557 }
12558 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12559 if(not $Allocable)
12560 { # check bases
12561 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12562 {
12563 if(not isCopyingClass($DCId, $LibVersion))
12564 { # exists a derived class without default c-tor
12565 $Allocable=1;
12566 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012568 }
12569 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012570 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012571 return 0;
12572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012573 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012574 else
12575 { # inline non-virtual methods
12576 return 0;
12577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 }
12580 }
12581 return 1;
12582}
12583
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012584sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012585{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012586 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12588 {
12589 if(link_symbol($Symbol, 1, "+Deps"))
12590 { # linker can find a new symbol
12591 # in the old-version library
12592 # So, it's not a new symbol
12593 next;
12594 }
12595 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597 next;
12598 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012599 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600 }
12601}
12602
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012603sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012605 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012606 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12607 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608 if(link_symbol($Symbol, 2, "+Deps"))
12609 { # linker can find an old symbol
12610 # in the new-version library
12611 next;
12612 }
12613 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012614 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 next;
12616 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012617 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 }
12619}
12620
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012621sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012622{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012623 my $Level = $_[0];
12624 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 { # checking added symbols
12626 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012627 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012628 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012629 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012630 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012631 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632 { # checking removed symbols
12633 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012634 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012635 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012636 { # skip v-tables for templates, that should not be imported by applications
12637 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012638 if(my $CName = $VTableClass{$Symbol})
12639 {
12640 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12641 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012642 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012643 next;
12644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012645 }
12646 }
12647 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012648 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012649 }
12650 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12651 { # symbols for pure virtual methods cannot be called by clients
12652 next;
12653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012654 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 }
12656}
12657
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012658sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012660 my ($LibVersion, $V) = @_;
12661 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12662 return $Cache{"checkDump"}{$LibVersion}{$V};
12663 }
12664 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012665}
12666
12667sub detectAdded_H($)
12668{
12669 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012670 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12671 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012672 if($Level eq "Source")
12673 { # remove symbol version
12674 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12675 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012676
12677 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12678 { # skip artificial constructors
12679 next;
12680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012681 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012682 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12683 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012684 next;
12685 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012686 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012687 next;
12688 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012689 if(not defined $CompleteSignature{1}{$Symbol}
12690 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12691 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012692 if($UsedDump{2}{"SrcBin"})
12693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012694 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012695 { # support for old and different (!) ABI dumps
12696 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12697 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012698 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012699 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012700 {
12701 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12702 {
12703 if($Lang eq "C")
12704 { # support for old ABI dumps: missed extern "C" functions
12705 next;
12706 }
12707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012708 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012709 else
12710 {
12711 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012712 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012713 next;
12714 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 }
12716 }
12717 }
12718 }
12719 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012720 }
12721 }
12722}
12723
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012724sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012725{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012726 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012727 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12728 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012729 if($Level eq "Source")
12730 { # remove symbol version
12731 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12732 $Symbol=$SN;
12733 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012734 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12735 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012736 next;
12737 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012738 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012739 next;
12740 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012741 if(not defined $CompleteSignature{2}{$Symbol}
12742 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012743 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012744 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012745 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012746 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012747 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012748 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12749 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012750 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012751 if($CheckHeadersOnly)
12752 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012753 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12754 {
12755 if($Lang eq "C")
12756 { # support for old ABI dumps: missed extern "C" functions
12757 next;
12758 }
12759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012761 else
12762 {
12763 if(not link_symbol($Symbol, 1, "-Deps"))
12764 { # skip removed inline symbols
12765 next;
12766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 }
12768 }
12769 }
12770 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012771 if(not checkDump(1, "2.15"))
12772 {
12773 if($Symbol=~/_IT_E\Z/)
12774 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12775 next;
12776 }
12777 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012778 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12779 {
12780 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12781 {
12782 if(defined $Constants{2}{$Short})
12783 {
12784 my $Val = $Constants{2}{$Short}{"Value"};
12785 if(defined $Func_ShortName{2}{$Val})
12786 { # old name defined to new
12787 next;
12788 }
12789 }
12790 }
12791
12792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012793 $RemovedInt{$Level}{$Symbol} = 1;
12794 if($Level eq "Source")
12795 { # search for a source-compatible equivalent
12796 setAlternative($Symbol, $Level);
12797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 }
12799 }
12800}
12801
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012802sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012804 my $Level = $_[0];
12805 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 { # checking added symbols
12807 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012808 next if($CompleteSignature{2}{$Symbol}{"Private"});
12809 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012810 if($Level eq "Binary")
12811 {
12812 if($CompleteSignature{2}{$Symbol}{"InLine"})
12813 {
12814 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12815 { # skip inline non-virtual functions
12816 next;
12817 }
12818 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012819 }
12820 else
12821 { # Source
12822 if($SourceAlternative_B{$Symbol}) {
12823 next;
12824 }
12825 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012826 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012828 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012829 { # checking removed symbols
12830 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012831 next if($CompleteSignature{1}{$Symbol}{"Private"});
12832 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012833 if($Level eq "Binary")
12834 {
12835 if($CompleteSignature{1}{$Symbol}{"InLine"})
12836 {
12837 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12838 { # skip inline non-virtual functions
12839 next;
12840 }
12841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 }
12843 else
12844 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012845 if(my $Alt = $SourceAlternative{$Symbol})
12846 {
12847 if(defined $CompleteSignature{1}{$Alt}
12848 and $CompleteSignature{1}{$Symbol}{"Const"})
12849 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012850 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012851 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012852 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012853 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012854 }
12855 else
12856 { # do NOT show removed symbol
12857 next;
12858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 }
12860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012862 }
12863}
12864
12865sub addParamNames($)
12866{
12867 my $LibraryVersion = $_[0];
12868 return if(not keys(%AddIntParams));
12869 my $SecondVersion = $LibraryVersion==1?2:1;
12870 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12871 {
12872 next if(not keys(%{$AddIntParams{$Interface}}));
12873 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012874 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012875 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12876 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012877 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12879 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12880 {
12881 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12882 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12883 }
12884 }
12885 else {
12886 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12887 }
12888 }
12889 }
12890 }
12891}
12892
12893sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012894{ # detect changed typedefs to show
12895 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012896 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12897 {
12898 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012899 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12900 if(not $BName1 or isAnon($BName1)) {
12901 next;
12902 }
12903 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12904 if(not $BName2 or isAnon($BName2)) {
12905 next;
12906 }
12907 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012908 $ChangedTypedef{$Typedef} = 1;
12909 }
12910 }
12911}
12912
12913sub get_symbol_suffix($$)
12914{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 my ($Symbol, $Full) = @_;
12916 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012917 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012918 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012919 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012920 if(not $Full) {
12921 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12922 }
12923 return $Suffix;
12924}
12925
12926sub get_symbol_prefix($$)
12927{
12928 my ($Symbol, $LibVersion) = @_;
12929 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12930 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12931 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012932 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012933 }
12934 return $ShortName;
12935}
12936
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012937sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012938{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012939 my $Symbol = $_[0];
12940 my $PSymbol = $Symbol;
12941 if(not defined $CompleteSignature{2}{$PSymbol}
12942 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12943 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12944 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012945 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012947 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012948 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012949 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12950 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012951 {
12952 if(defined $CompleteSignature{2}{$PSymbol}
12953 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12954 {
12955 $SourceAlternative{$Symbol} = $PSymbol;
12956 $SourceAlternative_B{$PSymbol} = $Symbol;
12957 if(not defined $CompleteSignature{1}{$PSymbol}
12958 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12959 $SourceReplacement{$Symbol} = $PSymbol;
12960 }
12961 }
12962 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012963 }
12964 else
12965 {
12966 foreach my $Sp ("KV", "VK", "K", "V")
12967 {
12968 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12969 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12970 {
12971 if(defined $CompleteSignature{2}{$PSymbol}
12972 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12973 {
12974 $SourceAlternative{$Symbol} = $PSymbol;
12975 $SourceAlternative_B{$PSymbol} = $Symbol;
12976 if(not defined $CompleteSignature{1}{$PSymbol}
12977 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12978 $SourceReplacement{$Symbol} = $PSymbol;
12979 }
12980 }
12981 }
12982 $PSymbol = $Symbol;
12983 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 }
12985 }
12986 }
12987 return "";
12988}
12989
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012990sub getSymKind($$)
12991{
12992 my ($Symbol, $LibVersion) = @_;
12993 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12994 {
12995 return "Global_Data";
12996 }
12997 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12998 {
12999 return "Method";
13000 }
13001 return "Function";
13002}
13003
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013004sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013005{
13006 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013007 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013008
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013009 mergeBases($Level);
13010
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013011 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013012 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013013 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013014 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013015 next;
13016 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013017 if(defined $CompleteSignature{1}{$Symbol}
13018 and $CompleteSignature{1}{$Symbol}{"Header"})
13019 { # double-check added symbol
13020 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013021 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013022 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013023 next;
13024 }
13025 if($Symbol=~/\A(_Z|\?)/)
13026 { # C++
13027 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13028 }
13029 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13030 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013031 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13032 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013033 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013034 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013035 {
13036 if($TName_Tid{1}{$AffectedClass_Name})
13037 { # class should exist in previous version
13038 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13039 { # old v-table is NOT copied by old applications
13040 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13041 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013042 "Target"=>get_Signature($Symbol, 2),
13043 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013044 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013047 }
13048 }
13049 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013050 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13051 { # check all removed exported symbols
13052 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013053 next;
13054 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013055 if(defined $CompleteSignature{2}{$Symbol}
13056 and $CompleteSignature{2}{$Symbol}{"Header"})
13057 { # double-check removed symbol
13058 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013059 }
13060 if($CompleteSignature{1}{$Symbol}{"Private"})
13061 { # skip private methods
13062 next;
13063 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013064 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013065 next;
13066 }
13067 $CheckedSymbols{$Level}{$Symbol} = 1;
13068 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13069 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013070 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13071 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013072 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013073 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13074 {
13075 if($TName_Tid{2}{$AffectedClass_Name})
13076 { # class should exist in newer version
13077 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13078 { # old v-table is NOT copied by old applications
13079 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13080 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013081 "Target"=>get_Signature($OverriddenMethod, 1),
13082 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013083 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 }
13087 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013088 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013089 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013090 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013091 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013092 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013093 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013094 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013095 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013096 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013097 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013098 {
13099 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13100 "Target"=>$tr_name{$Symbol},
13101 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013102 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104 else
13105 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013106 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013107 "Target"=>$tr_name{$Symbol},
13108 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013109 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013110 }
13111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013112 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013114 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013115 {
13116 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13117 "Target"=>$tr_name{$Symbol},
13118 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013119 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013121 else
13122 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013123 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013124 "Target"=>$tr_name{$Symbol},
13125 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013126 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013127 }
13128 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013129 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13130 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13131 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13132 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13133 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013134 {
13135 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013136 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013137 $ProblemType = "Global_Data_Symbol_Changed_Type";
13138 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013139 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13140 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013141 "Old_Type"=>$RTName1,
13142 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013143 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013144 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013145 }
13146 }
13147 }
13148 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013149 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013150 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013152 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013154 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013155 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013156 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13157 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013158 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013159 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013160 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013161 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013162 }
13163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013164 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13165 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013166 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013167 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013169 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 }
13171 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013172 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013173 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013174 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013175 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013176 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013177 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013179 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013180 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013182 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013183 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013184 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013187 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013189 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013190 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013191 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013192 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013193 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013195 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013196 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013197 { # "volatile" to non-"volatile"
13198
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013199 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013201 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013202 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013203 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013205 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013206 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013207 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013208 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013209 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013210 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013211 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013212 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013213 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013214 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013215 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13217 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013218 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013219 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013220 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013221 }
13222 }
13223 }
13224 }
13225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13227 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013228 $CurrentSymbol = $Symbol;
13229
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013230 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13231 if($Level eq "Source")
13232 { # remove symbol version
13233 $Symbol=$SN;
13234 }
13235 else
13236 { # Binary
13237 if(not $SV)
13238 { # symbol without version
13239 if(my $VSym = $SymVer{1}{$Symbol})
13240 { # the symbol is linked with versioned symbol
13241 if($CompleteSignature{2}{$VSym}{"MnglName"})
13242 { # show report for symbol@ver only
13243 next;
13244 }
13245 elsif(not link_symbol($VSym, 2, "-Deps"))
13246 { # changed version: sym@v1 to sym@v2
13247 # do NOT show report for symbol
13248 next;
13249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013250 }
13251 }
13252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013253 my $PSymbol = $Symbol;
13254 if($Level eq "Source"
13255 and my $S = $SourceReplacement{$Symbol})
13256 { # take a source-compatible replacement function
13257 $PSymbol = $S;
13258 }
13259 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 { # private symbols
13261 next;
13262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013263 if(not defined $CompleteSignature{1}{$Symbol}
13264 or not defined $CompleteSignature{2}{$PSymbol})
13265 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 next;
13267 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013268 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13269 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13270 { # no mangled name
13271 next;
13272 }
13273 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13274 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013275 { # without a header
13276 next;
13277 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013278
13279 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13280 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13281 { # became pure
13282 next;
13283 }
13284 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13285 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13286 { # became non-pure
13287 next;
13288 }
13289
13290 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13291 { # exported, target, inline virtual and pure virtual
13292 next;
13293 }
13294 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13295 { # exported, target, inline virtual and pure virtual
13296 next;
13297 }
13298
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013299 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013300 {
13301 if($CompleteSignature{1}{$Symbol}{"Data"}
13302 and $CompleteSignature{2}{$PSymbol}{"Data"})
13303 {
13304 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13305 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13306 if(defined $Value1)
13307 {
13308 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13309 if(defined $Value2)
13310 {
13311 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13312 if($Value1 ne $Value2)
13313 {
13314 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13315 "Old_Value"=>$Value1,
13316 "New_Value"=>$Value2,
13317 "Target"=>get_Signature($Symbol, 1) );
13318 }
13319 }
13320 }
13321 }
13322 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013323
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013324 if($CompleteSignature{2}{$PSymbol}{"Private"})
13325 {
13326 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13327 "Target"=>get_Signature_M($PSymbol, 2) );
13328 }
13329 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13330 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13331 {
13332 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13333 "Target"=>get_Signature_M($PSymbol, 2) );
13334 }
13335 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13336 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13337 {
13338 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13339 "Target"=>get_Signature_M($PSymbol, 2) );
13340 }
13341
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013343 mergeVirtualTables($Symbol, $Level);
13344
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013345 if($COMPILE_ERRORS)
13346 { # if some errors occurred at the compiling stage
13347 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013350 { # missed information about parameters in newer version
13351 next;
13352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013354 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013355 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013356 next;
13357 }
13358 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013360 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013362 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13363 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013364 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13365 "Target"=>get_Signature($Symbol, 1)
13366 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013367 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013369 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13370 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013371 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Target"=>get_Signature($Symbol, 1)
13373 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13376 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013377 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013380 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13381 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13382 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013385 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13386 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013387 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013388 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 my $ProblemType = "Virtual_Method_Position";
13390 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13391 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013393 if(isUsedClass($Class_Id, 1, $Level))
13394 {
13395 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013396 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013398 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13399 next;
13400 }
13401 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013403 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13404 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013405 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013407 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013409 }
13410 }
13411 }
13412 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013413 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13414 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013415 { # do NOT check type changes in pure virtuals
13416 next;
13417 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013418 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 if($Symbol=~/\A(_Z|\?)/
13420 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013422 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013424 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013425 }
13426 }
13427 else
13428 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013429 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013431 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013432 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13433 last if($PType2_Name eq "...");
13434 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13435 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013436 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013438 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013439 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13440 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013441 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13442 $ParamPos_Prev = "lost";
13443 }
13444 }
13445 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013446 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013447 }
13448 if($ParamPos_Prev eq "lost")
13449 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013451 {
13452 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013453 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013454 $ProblemType = "Added_Unnamed_Parameter";
13455 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013456 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013457 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013458 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013459 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 }
13462 else
13463 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013464 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013465 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013466 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13468 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013469 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013470 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013472 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013473 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013474 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 "Param_Type"=>$PType2_Name,
13476 "Old_Value"=>$PName_Old,
13477 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013478 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013479 }
13480 }
13481 else
13482 {
13483 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013484 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 $ProblemType = "Added_Middle_Unnamed_Parameter";
13486 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013487 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013488 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013489 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013490 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013491 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013492 }
13493 }
13494 }
13495 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013496 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013497 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013498 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013499 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013500 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013502 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013503 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013504 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013505 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13506 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013507 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013508 }
13509 }
13510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013511 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013512 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013513 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013514 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13515 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013516 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13517 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013518 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013519 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013521 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13522 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13524 $ParamPos_New = "lost";
13525 }
13526 }
13527 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013528 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013529 }
13530 if($ParamPos_New eq "lost")
13531 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013532 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 {
13534 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013535 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013536 $ProblemType = "Removed_Unnamed_Parameter";
13537 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013538 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013539 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013540 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013541 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013543 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013544 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013545 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013546 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013547 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013548 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013549 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013550 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013551 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013552 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013554 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013555 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013556 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013557 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013558 "Old_Value"=>$PName,
13559 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013560 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 }
13562 }
13563 else
13564 {
13565 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013566 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13568 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013569 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013570 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013571 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013572 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013574 }
13575 }
13576 }
13577 }
13578 }
13579 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013580 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13581 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013582 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013583
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013584 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013586 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13587 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013588 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013589
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013590 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013592 if($SubProblemType eq "Return_Type_And_Size") {
13593 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13594 }
13595 elsif($SubProblemType eq "Return_Type_Format") {
13596 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13597 }
13598 else {
13599 $ProblemTypes{"Global_Data_Type"} = 1;
13600 }
13601
13602 # quals
13603 if($SubProblemType eq "Return_Type"
13604 or $SubProblemType eq "Return_Type_And_Size"
13605 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013606 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013607 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13608 { # const to non-const
13609 if($RR==2) {
13610 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13611 }
13612 else {
13613 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13614 }
13615 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013617 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13618 { # non-const to const
13619 if($RA==2) {
13620 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13621 }
13622 else {
13623 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13624 }
13625 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013626 }
13627 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013628 }
13629 else
13630 {
13631 # quals
13632 if($SubProblemType eq "Return_Type"
13633 or $SubProblemType eq "Return_Type_And_Size"
13634 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013636 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013637 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013638 if(addedQual($Old_Value, $New_Value, "volatile"))
13639 {
13640 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13641 if($Level ne "Source"
13642 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13643 $ProblemTypes{"Return_Type"} = 1;
13644 }
13645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013646 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013647 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13648 {
13649 if($RA==2) {
13650 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13651 }
13652 else {
13653 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13654 }
13655 if($Level ne "Source"
13656 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13657 $ProblemTypes{"Return_Type"} = 1;
13658 }
13659 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013660 }
13661 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013662 if($Level eq "Binary"
13663 and not $CompleteSignature{1}{$Symbol}{"Data"})
13664 {
13665 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13666 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13667 { # if one of the architectures is unknown
13668 # then set other arhitecture to unknown too
13669 ($Arch1, $Arch2) = ("unknown", "unknown");
13670 }
13671 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013672 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013673 {
13674 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13675 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13676 }
13677 else
13678 {
13679 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13680 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13681 }
13682
13683 if($SubProblemType eq "Return_Type_Became_Void")
13684 {
13685 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13686 { # parameters stack has been affected
13687 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013688 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013689 }
13690 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013691 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013692 }
13693 }
13694 }
13695 elsif($SubProblemType eq "Return_Type_From_Void")
13696 {
13697 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13698 { # parameters stack has been affected
13699 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013700 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013701 }
13702 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013703 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013704 }
13705 }
13706 }
13707 elsif($SubProblemType eq "Return_Type"
13708 or $SubProblemType eq "Return_Type_And_Size"
13709 or $SubProblemType eq "Return_Type_Format")
13710 {
13711 if($Conv1{"Method"} ne $Conv2{"Method"})
13712 {
13713 if($Conv1{"Method"} eq "stack")
13714 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013715 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013716 }
13717 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013718 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013719 }
13720 }
13721 else
13722 {
13723 if($Conv1{"Method"} eq "reg")
13724 {
13725 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13726 {
13727 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013728 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013729 }
13730 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013731 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013732 }
13733 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013734 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013735 }
13736 }
13737 }
13738 }
13739 }
13740 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013741
13742 if(not keys(%ProblemTypes))
13743 { # default
13744 $ProblemTypes{$SubProblemType} = 1;
13745 }
13746
13747 foreach my $ProblemType (keys(%ProblemTypes))
13748 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013749 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013751 }
13752 if($ReturnType1_Id and $ReturnType2_Id)
13753 {
13754 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013755 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13756
13757 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013758
13759 if($CompleteSignature{1}{$Symbol}{"Data"})
13760 {
13761 if($Level eq "Binary")
13762 {
13763 if(get_PLevel($ReturnType1_Id, 1)==0)
13764 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013765 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013766 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013767
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013768 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13769 {
13770 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013771 {
13772 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13773 {
13774 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13775 last;
13776 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013777 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013778 }
13779 }
13780 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013781 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013782 {
13783 if(defined $GlobalDataObject{1}{$Symbol}
13784 and defined $GlobalDataObject{2}{$Symbol})
13785 {
13786 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13787 my $New_Size = $GlobalDataObject{2}{$Symbol};
13788 if($Old_Size!=$New_Size)
13789 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013790 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013791 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013792 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013793 }
13794 }
13795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013796 }
13797 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013798
13799 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013800 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013801 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013803 my $NewLocation = "retval";
13804 if($SubLocation and $SubLocation ne "retval") {
13805 $NewLocation = "retval->".$SubLocation;
13806 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013807 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13808 }
13809 }
13810
13811 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13812 {
13813 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13814 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013815 my $NewLocation = "retval";
13816 if($SubLocation and $SubLocation ne "retval") {
13817 $NewLocation = "retval->".$SubLocation;
13818 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013819 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013820 }
13821 }
13822 }
13823
13824 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013825 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13826 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13827 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013828 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013829 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013830 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13831 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013832 if($ThisPtr1_Id and $ThisPtr2_Id)
13833 {
13834 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013835 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13836 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013837 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013838 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839 {
13840 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013841 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013842 }
13843 }
13844 }
13845 }
13846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013847 if($Level eq "Binary") {
13848 mergeVTables($Level);
13849 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013850 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13851 $CheckedSymbols{$Level}{$Symbol} = 1;
13852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013853}
13854
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013855sub rmQuals($$)
13856{
13857 my ($Value, $Qual) = @_;
13858 if(not $Qual) {
13859 return $Value;
13860 }
13861 if($Qual eq "all")
13862 { # all quals
13863 $Qual = "const|volatile|restrict";
13864 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013865 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013866 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013867 }
13868 return $Value;
13869}
13870
13871sub cmpBTypes($$$$)
13872{
13873 my ($T1, $T2, $V1, $V2) = @_;
13874 $T1 = uncover_typedefs($T1, $V1);
13875 $T2 = uncover_typedefs($T2, $V2);
13876 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13877}
13878
13879sub addedQual($$$)
13880{
13881 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013882 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013883}
13884
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013885sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013886{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013887 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013888 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013889}
13890
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013891sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013892{
13893 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13894 $Old_Value = uncover_typedefs($Old_Value, $V1);
13895 $New_Value = uncover_typedefs($New_Value, $V2);
13896 if($Old_Value eq $New_Value)
13897 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013898 return 0;
13899 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013900 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013901 { # without a qual
13902 return 0;
13903 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013904 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013905 { # became non-qual
13906 return 1;
13907 }
13908 else
13909 {
13910 my @BQ1 = getQualModel($Old_Value, $Qual);
13911 my @BQ2 = getQualModel($New_Value, $Qual);
13912 foreach (0 .. $#BQ1)
13913 { # removed qual
13914 if($BQ1[$_]==1
13915 and $BQ2[$_]!=1)
13916 {
13917 return 2;
13918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013919 }
13920 }
13921 return 0;
13922}
13923
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013924sub getQualModel($$)
13925{
13926 my ($Value, $Qual) = @_;
13927 if(not $Qual) {
13928 return $Value;
13929 }
13930
13931 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013932 while($Value=~/(\w+)/ and $1 ne $Qual) {
13933 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013934 }
13935 $Value=~s/[^\*\&\w]+//g;
13936
13937 # modeling
13938 # int*const*const == 011
13939 # int**const == 001
13940 my @Model = ();
13941 my @Elems = split(/[\*\&]/, $Value);
13942 if(not @Elems) {
13943 return (0);
13944 }
13945 foreach (@Elems)
13946 {
13947 if($_ eq $Qual) {
13948 push(@Model, 1);
13949 }
13950 else {
13951 push(@Model, 0);
13952 }
13953 }
13954
13955 return @Model;
13956}
13957
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013958my %StringTypes = map {$_=>1} (
13959 "char*",
13960 "char const*"
13961);
13962
13963my %CharTypes = map {$_=>1} (
13964 "char",
13965 "char const"
13966);
13967
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013968sub showVal($$$)
13969{
13970 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013971 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013972 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013973 if(substr($Value, 0, 2) eq "_Z")
13974 {
13975 if(my $Unmangled = $tr_name{$Value}) {
13976 return $Unmangled;
13977 }
13978 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013979 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013980 { # strings
13981 return "\"$Value\"";
13982 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013983 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013984 { # characters
13985 return "\'$Value\'";
13986 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013987 if($Value eq "")
13988 { # other
13989 return "\'\'";
13990 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013991 return $Value;
13992}
13993
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013994sub getRegs($$$)
13995{
13996 my ($LibVersion, $Symbol, $Pos) = @_;
13997
13998 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13999 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014000 my %Regs = ();
14001 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14002 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014003 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014004 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14005 }
14006 }
14007
14008 return join(", ", sort keys(%Regs));
14009 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014010 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14011 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14012 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14013 {
14014 return "unknown";
14015 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014016
14017 return undef;
14018}
14019
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014020sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014021{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014022 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014023 if(not $Symbol) {
14024 return;
14025 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014026 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14027 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14028 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14029 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014030 if(not $PType1_Id
14031 or not $PType2_Id) {
14032 return;
14033 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014034
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014035 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014036 { # do not merge "this"
14037 if($PName1 eq "this" or $PName2 eq "this") {
14038 return;
14039 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014040 }
14041
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014042 my %Type1 = get_Type($PType1_Id, 1);
14043 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014044
14045 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14046
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014047 my %BaseType1 = get_BaseType($PType1_Id, 1);
14048 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014049
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014050 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014051
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014052 if($Level eq "Binary")
14053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014054 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014055 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14056 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14057 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14058 {
14059 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014060 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014061 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014062 }
14063 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14064 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14065 {
14066 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014067 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014068 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014070 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014071
14072 if(defined $UsedDump{1}{"DWARF"}
14073 and defined $UsedDump{2}{"DWARF"})
14074 {
14075 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14076 {
14077 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14078 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014079
14080 if($Old_Regs ne "unknown"
14081 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014082 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014083 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014084 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014085 if($Old_Regs ne $New_Regs)
14086 {
14087 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14088 "Target"=>$PName1,
14089 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14090 "Old_Value"=>$Old_Regs,
14091 "New_Value"=>$New_Regs );
14092 }
14093 }
14094 elsif($Old_Regs and not $New_Regs)
14095 {
14096 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014097 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014098 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014099 "Old_Value"=>$Old_Regs );
14100 }
14101 elsif(not $Old_Regs and $New_Regs)
14102 {
14103 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14104 "Target"=>$PName1,
14105 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014106 "New_Value"=>$New_Regs );
14107 }
14108 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014109
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014110 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14111 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14112 {
14113 if($Old_Offset ne $New_Offset)
14114 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014115 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14116 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14117
14118 $Old_Offset = $Old_Offset - $Start1;
14119 $New_Offset = $New_Offset - $Start2;
14120
14121 if($Old_Offset ne $New_Offset)
14122 {
14123 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14124 "Target"=>$PName1,
14125 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14126 "Old_Value"=>$Old_Offset,
14127 "New_Value"=>$New_Offset );
14128 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014129 }
14130 }
14131 }
14132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014133 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014134 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14135 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014136 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014137 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014138 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14139 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014140 if(not checkDump(1, "2.13")
14141 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014142 { # support for old ABI dumps
14143 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014144 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014145 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014146 and $Value_Old eq "false" and $Value_New eq "0")
14147 { # int class::method ( bool p = 0 );
14148 # old ABI dumps: "false"
14149 # new ABI dumps: "0"
14150 $Value_Old = "0";
14151 }
14152 }
14153 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014154 if(not checkDump(1, "2.18")
14155 and checkDump(2, "2.18"))
14156 { # support for old ABI dumps
14157 if(not defined $Value_Old
14158 and substr($Value_New, 0, 2) eq "_Z") {
14159 $Value_Old = $Value_New;
14160 }
14161 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014162 if(defined $Value_Old)
14163 {
14164 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14165 if(defined $Value_New)
14166 {
14167 $Value_New = showVal($Value_New, $PType2_Id, 2);
14168 if($Value_Old ne $Value_New)
14169 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014170 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014171 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014172 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014173 "Old_Value"=>$Value_Old,
14174 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014175 }
14176 }
14177 else
14178 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014179 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014180 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014181 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014183 }
14184 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014185 elsif(defined $Value_New)
14186 {
14187 $Value_New = showVal($Value_New, $PType2_Id, 2);
14188 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14189 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014190 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014191 "New_Value"=>$Value_New );
14192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014193 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014194
14195 if($ChkRnmd)
14196 {
14197 if($PName1 and $PName2 and $PName1 ne $PName2
14198 and $PType1_Id!=-1 and $PType2_Id!=-1
14199 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14200 { # except unnamed "..." value list (Id=-1)
14201 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14202 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014203 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014204 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14205 "Old_Value"=>$PName1,
14206 "New_Value"=>$PName2,
14207 "New_Signature"=>get_Signature($Symbol, 2) );
14208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014209 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014211 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014212 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014213
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014214 foreach my $SubProblemType (keys(%SubProblems))
14215 { # add new problems, remove false alarms
14216 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14217 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014218
14219 # quals
14220 if($SubProblemType eq "Parameter_Type"
14221 or $SubProblemType eq "Parameter_Type_And_Size"
14222 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014223 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014224 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014225 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014226 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014227 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014228 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014229 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14230 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14231 }
14232 }
14233 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14234 {
14235 if(removedQual($Old_Value, $New_Value, "volatile")) {
14236 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014237 }
14238 }
14239 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14240 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14241 { # int to "int const"
14242 delete($SubProblems{$SubProblemType});
14243 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014244 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014245 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14246 { # "int const" to int
14247 delete($SubProblems{$SubProblemType});
14248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014249 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14250 { # "const" to non-"const"
14251 if($RR==2) {
14252 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14253 }
14254 else {
14255 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14256 }
14257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014258 }
14259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014260
14261 if($Level eq "Source")
14262 {
14263 foreach my $SubProblemType (keys(%SubProblems))
14264 {
14265 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14266 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14267
14268 if($SubProblemType eq "Parameter_Type")
14269 {
14270 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14271 delete($SubProblems{$SubProblemType});
14272 }
14273 }
14274 }
14275 }
14276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014277 foreach my $SubProblemType (keys(%SubProblems))
14278 { # modify/register problems
14279 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14280 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014281 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14282 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014283
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014284 my $NewProblemType = $SubProblemType;
14285 if($Old_Value eq "..." and $New_Value ne "...")
14286 { # change from "..." to "int"
14287 if($ParamPos1==0)
14288 { # ISO C requires a named argument before "..."
14289 next;
14290 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014291 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014292 }
14293 elsif($New_Value eq "..." and $Old_Value ne "...")
14294 { # change from "int" to "..."
14295 if($ParamPos2==0)
14296 { # ISO C requires a named argument before "..."
14297 next;
14298 }
14299 $NewProblemType = "Parameter_Became_VaList";
14300 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014301 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014302 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014303 {
14304 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014305 if($Arch1 eq "unknown"
14306 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014307 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014308 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014309 ($Arch1, $Arch2) = ("unknown", "unknown");
14310 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014311 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014312 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014313 { # real
14314 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14315 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14316 }
14317 else
14318 { # model
14319 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14320 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14321 }
14322 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014323 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014324 if($Conv1{"Method"} eq "stack")
14325 {
14326 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14327 $NewProblemType = "Parameter_Type_And_Stack";
14328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014329 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014330 elsif($Conv1{"Method"} eq "reg")
14331 {
14332 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14333 $NewProblemType = "Parameter_Type_And_Register";
14334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014335 }
14336 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014337 elsif($Conv1{"Method"} ne "unknown"
14338 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014339 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014340 if($Conv1{"Method"} eq "stack") {
14341 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014342 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014343 elsif($Conv1{"Method"} eq "register") {
14344 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014345 }
14346 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014347 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14348 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014350 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014351 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014352 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014353 "New_Signature"=>get_Signature($Symbol, 2) );
14354 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014355 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014357 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014360 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14361 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014362 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014363 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014364 {
14365 my $NewProblemType = $SubProblemType;
14366 if($SubProblemType eq "DataType_Size")
14367 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014368 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014369 { # stack has been affected
14370 $NewProblemType = "DataType_Size_And_Stack";
14371 }
14372 }
14373 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014374 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014375 }
14376 }
14377}
14378
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379sub find_ParamPair_Pos_byName($$$)
14380{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014381 my ($Name, $Symbol, $LibVersion) = @_;
14382 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014383 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014384 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14385 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 {
14387 return $ParamPos;
14388 }
14389 }
14390 return "lost";
14391}
14392
14393sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14394{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014395 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014397 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014398 {
14399 next if($Order eq "backward" and $ParamPos>$MediumPos);
14400 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014401 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14402 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014403 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014404 push(@Positions, $ParamPos);
14405 }
14406 }
14407 return @Positions;
14408}
14409
14410sub getTypeIdByName($$)
14411{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014412 my ($TypeName, $LibVersion) = @_;
14413 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414}
14415
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014416sub diffTypes($$$)
14417{
14418 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14419 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14420 }
14421 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14422 { # skip recursive declarations
14423 return 0;
14424 }
14425
14426 pushType($_[0], $_[1], \@RecurTypes_Diff);
14427 my $Diff = diffTypes_I(@_);
14428 pop(@RecurTypes_Diff);
14429
14430 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14431}
14432
14433sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014434{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014435 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014436
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014437 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14438 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014440 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14441 { # equal types
14442 return 0;
14443 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014444 if($Type1_Pure{"Name"} eq "void")
14445 { # from void* to something
14446 return 0;
14447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014448 if($Type1_Pure{"Name"}=~/\*/
14449 or $Type2_Pure{"Name"}=~/\*/)
14450 { # compared in detectTypeChange()
14451 return 0;
14452 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014454 my %FloatType = map {$_=>1} (
14455 "float",
14456 "double",
14457 "long double"
14458 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014459
14460 my $T1 = $Type1_Pure{"Type"};
14461 my $T2 = $Type2_Pure{"Type"};
14462
14463 if($T1 eq "Struct"
14464 and $T2 eq "Class")
14465 { # compare as data structures
14466 $T2 = "Struct";
14467 }
14468
14469 if($T1 eq "Class"
14470 and $T2 eq "Struct")
14471 { # compare as data structures
14472 $T1 = "Struct";
14473 }
14474
14475 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014476 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014477 if($T1 eq "Intrinsic"
14478 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 { # "int" to "enum"
14480 return 0;
14481 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014482 elsif($T2 eq "Intrinsic"
14483 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014484 { # "enum" to "int"
14485 return 0;
14486 }
14487 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014488 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 # ...
14490 return 1;
14491 }
14492 }
14493 else
14494 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014495 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014496 {
14497 if($FloatType{$Type1_Pure{"Name"}}
14498 or $FloatType{$Type2_Pure{"Name"}})
14499 { # "float" to "double"
14500 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014501 if($Level eq "Source")
14502 { # Safe
14503 return 0;
14504 }
14505 else {
14506 return 1;
14507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508 }
14509 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014510 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014511 {
14512 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14513 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014514 if(not @Membs1
14515 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014516 { # private
14517 return 0;
14518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014519 if($#Membs1!=$#Membs2)
14520 { # different number of elements
14521 return 1;
14522 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014523 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014524 {
14525 foreach my $Pos (@Membs1)
14526 { # compare elements by name and value
14527 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14528 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14529 { # different names
14530 return 1;
14531 }
14532 }
14533 }
14534 else
14535 {
14536 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014537 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014538 if($Level eq "Source")
14539 {
14540 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14541 { # different names
14542 return 1;
14543 }
14544 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014545
14546 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14547 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14548
14549 if($MT1{"Name"} ne $MT2{"Name"}
14550 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14551 {
14552 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14553 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14554
14555 if($PL1 ne $PL2)
14556 { # different pointer level
14557 return 1;
14558 }
14559
14560 # compare base types
14561 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14562 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14563
14564 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14565 { # different types
14566 return 1;
14567 }
14568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014569 }
14570 }
14571 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014572 else
14573 {
14574 # TODO: arrays, etc.
14575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576 }
14577 return 0;
14578}
14579
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014580sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014581{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014582 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014583 if(not $Type1_Id or not $Type2_Id) {
14584 return ();
14585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014586 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014587 my %Type1 = get_Type($Type1_Id, 1);
14588 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014589 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14590 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14591 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14592 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 +040014593
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014594 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14595 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014596 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14597 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14598 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14599 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14600 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14601 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14602 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014603 if($Type1{"Name"} eq $Type2{"Name"})
14604 {
14605 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14606 { # will be reported in mergeTypes() as typedef problem
14607 return ();
14608 }
14609 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14610 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14611 if(%Typedef_1 and %Typedef_2)
14612 {
14613 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14614 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14615 { # const Typedef
14616 return ();
14617 }
14618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014619 }
14620 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014622 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014623 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14624 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625 {
14626 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14627 "Old_Value"=>$Type1_Base{"Name"},
14628 "New_Value"=>$Type2_Base{"Name"},
14629 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014630 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 }
14632 else
14633 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014634 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 { # format change
14636 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14637 "Old_Value"=>$Type1_Base{"Name"},
14638 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014639 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014640 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014641 }
14642 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14643 {
14644 %{$LocalProblems{$Prefix."_BaseType"}}=(
14645 "Old_Value"=>$Type1_Base{"Name"},
14646 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014647 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014648 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 }
14650 }
14651 }
14652 }
14653 elsif($Type1{"Name"} ne $Type2{"Name"})
14654 { # type change
14655 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14656 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014657 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014658 and $Type1_Pure{"Name"} eq "void")
14659 {
14660 %{$LocalProblems{"Return_Type_From_Void"}}=(
14661 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014662 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014664 elsif($Prefix eq "Return"
14665 and $Type2_Pure{"Name"} eq "void")
14666 {
14667 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14668 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014669 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014671 else
14672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014673 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014674 and $Type1{"Size"} and $Type2{"Size"}
14675 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014676 {
14677 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14678 "Old_Value"=>$Type1{"Name"},
14679 "New_Value"=>$Type2{"Name"},
14680 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014681 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014682 }
14683 else
14684 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014685 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 { # format change
14687 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14688 "Old_Value"=>$Type1{"Name"},
14689 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014690 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014691 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 }
14693 elsif(tNameLock($Type1_Id, $Type2_Id))
14694 { # FIXME: correct this condition
14695 %{$LocalProblems{$Prefix."_Type"}}=(
14696 "Old_Value"=>$Type1{"Name"},
14697 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014698 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014699 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014700 }
14701 }
14702 }
14703 }
14704 }
14705 if($Type1_PLevel!=$Type2_PLevel)
14706 {
14707 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14708 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14709 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014710 if($Level eq "Source")
14711 {
14712 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014713 "Old_Value"=>$Type1_PLevel,
14714 "New_Value"=>$Type2_PLevel);
14715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014716 else
14717 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014718 if($Type2_PLevel>$Type1_PLevel)
14719 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014720 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14721 "Old_Value"=>$Type1_PLevel,
14722 "New_Value"=>$Type2_PLevel);
14723 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014724 else
14725 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014726 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14727 "Old_Value"=>$Type1_PLevel,
14728 "New_Value"=>$Type2_PLevel);
14729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014730 }
14731 }
14732 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014733 if($Type1_Pure{"Type"} eq "Array"
14734 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 { # base_type[N] -> base_type[N]
14736 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014737 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 foreach my $SubProblemType (keys(%SubProblems))
14739 {
14740 $SubProblemType=~s/_Type/_BaseType/g;
14741 next if(defined $LocalProblems{$SubProblemType});
14742 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14743 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14744 }
14745 }
14746 }
14747 return %LocalProblems;
14748}
14749
14750sub tNameLock($$)
14751{
14752 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014753 my $Changed = 0;
14754 if(differentDumps("G"))
14755 { # different GCC versions
14756 $Changed = 1;
14757 }
14758 elsif(differentDumps("V"))
14759 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014760 if(not checkDump(1, "2.20")
14761 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014762 { # latest names update
14763 # 2.6: added restrict qualifier
14764 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014765 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014766 $Changed = 1;
14767 }
14768 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014769
14770 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14771 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14772
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014773 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14774 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14775
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014776 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014777 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014778 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014779 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014780 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014781 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014782 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014783 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014784 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014785 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014786 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14787 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14788 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014789 { # equal base types
14790 return 0;
14791 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014792
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014793 if(not checkDump(1, "2.13")
14794 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014795 { # broken array names in ABI dumps < 2.13
14796 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014797 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014798 return 0;
14799 }
14800 }
14801
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014802 if(not checkDump(1, "2.6")
14803 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014804 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014805 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014806 and $TN2=~/\brestrict\b/) {
14807 return 0;
14808 }
14809 }
14810
14811 if(not checkDump(1, "2.20")
14812 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014813 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014814 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14815 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014816 return 0;
14817 }
14818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014819 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014820 else
14821 {
14822 # typedef struct {...} type_t
14823 # typedef struct type_t {...} type_t
14824 if(index($TN1, " ".$TN2)!=-1)
14825 {
14826 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14827 return 0;
14828 }
14829 }
14830 if(index($TN2, " ".$TN1)!=-1)
14831 {
14832 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14833 return 0;
14834 }
14835 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014836
14837 if($TT1 eq "FuncPtr"
14838 and $TT2 eq "FuncPtr")
14839 {
14840 my $TN1_C = $TN1;
14841 my $TN2_C = $TN2;
14842
14843 $TN1_C=~s/\b(struct|union) //g;
14844 $TN2_C=~s/\b(struct|union) //g;
14845
14846 if($TN1_C eq $TN2_C) {
14847 return 0;
14848 }
14849 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014850 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014851
14852 my ($N1, $N2) = ($TN1, $TN2);
14853 $N1=~s/\b(struct|union) //g;
14854 $N2=~s/\b(struct|union) //g;
14855
14856 if($N1 eq $N2)
14857 { # QList<struct QUrl> and QList<QUrl>
14858 return 0;
14859 }
14860
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 return 1;
14862}
14863
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014864sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014866 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014867 if(defined $Cache{"differentDumps"}{$Check}) {
14868 return $Cache{"differentDumps"}{$Check};
14869 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014870 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014871 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014872 if($Check eq "G")
14873 {
14874 if(getGccVersion(1) ne getGccVersion(2))
14875 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014876 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014877 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014878 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014879 if($Check eq "V")
14880 {
14881 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14882 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14883 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014884 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014885 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014887 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014888 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889}
14890
14891sub formatVersion($$)
14892{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014893 my ($V, $Digits) = @_;
14894 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014895 return join(".", splice(@Elems, 0, $Digits));
14896}
14897
14898sub htmlSpecChars($)
14899{
14900 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014901 if(not $Str) {
14902 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14905 $Str=~s/</&lt;/g;
14906 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14907 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014908 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14909 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014910 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014911 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014912 $Str=~s/\n/<br\/>/g;
14913 $Str=~s/\"/&quot;/g;
14914 $Str=~s/\'/&#39;/g;
14915 return $Str;
14916}
14917
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014918sub xmlSpecChars($)
14919{
14920 my $Str = $_[0];
14921 if(not $Str) {
14922 return $Str;
14923 }
14924
14925 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14926 $Str=~s/</&lt;/g;
14927 $Str=~s/>/&gt;/g;
14928
14929 $Str=~s/\"/&quot;/g;
14930 $Str=~s/\'/&#39;/g;
14931
14932 return $Str;
14933}
14934
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014935sub xmlSpecChars_R($)
14936{
14937 my $Str = $_[0];
14938 if(not $Str) {
14939 return $Str;
14940 }
14941
14942 $Str=~s/&amp;/&/g;
14943 $Str=~s/&lt;/</g;
14944 $Str=~s/&gt;/>/g;
14945
14946 $Str=~s/&quot;/"/g;
14947 $Str=~s/&#39;/'/g;
14948
14949 return $Str;
14950}
14951
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014952sub black_name($)
14953{
14954 my $Name = $_[0];
14955 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14956}
14957
14958sub highLight_Signature($)
14959{
14960 my $Signature = $_[0];
14961 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14962}
14963
14964sub highLight_Signature_Italic_Color($)
14965{
14966 my $Signature = $_[0];
14967 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14968}
14969
14970sub separate_symbol($)
14971{
14972 my $Symbol = $_[0];
14973 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14974 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14975 ($Name, $Spec, $Ver) = ($1, $2, $3);
14976 }
14977 return ($Name, $Spec, $Ver);
14978}
14979
14980sub cut_f_attrs($)
14981{
14982 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14983 return $2;
14984 }
14985 return "";
14986}
14987
14988sub highLight_Signature_PPos_Italic($$$$$)
14989{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014990 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14991 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14993 my $Return = "";
14994 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14995 $Return = $2;
14996 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014997 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014998 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014999 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015000 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015001 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015002 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015003 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015004 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015005 }
15006 return $Signature;
15007 }
15008 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15009 $Begin.=" " if($Begin!~/ \Z/);
15010 $End = cut_f_attrs($Signature);
15011 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015012 my ($Short, $Params) = split_Signature($Signature);
15013 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015014 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015015 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015016 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015017 $Part=~s/\A\s+|\s+\Z//g;
15018 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15019 if($Part=~/\([\*]+(\w+)\)/i) {
15020 $ParamName = $1;#func-ptr
15021 }
15022 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15023 $ParamName = $1;
15024 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015025 if(not $ParamName)
15026 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 push(@Parts, $Part_Styled);
15028 next;
15029 }
15030 if($ItalicParams and not $TName_Tid{1}{$Part}
15031 and not $TName_Tid{2}{$Part})
15032 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015033 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015034 if($Param_Pos ne ""
15035 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015036 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015037 }
15038 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015039 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015040 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015041 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015042 }
15043 $Part_Styled=~s/,(\w)/, $1/g;
15044 push(@Parts, $Part_Styled);
15045 }
15046 if(@Parts)
15047 {
15048 foreach my $Num (0 .. $#Parts)
15049 {
15050 if($Num==$#Parts)
15051 { # add ")" to the last parameter
15052 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15053 }
15054 elsif(length($Parts[$Num])<=45) {
15055 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15056 }
15057 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015058 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015059 }
15060 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015061 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015062 }
15063 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015064 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015065 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015066 $Signature=~s!\[\]![&#160;]!g;
15067 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015068 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15069 if($SymbolVersion) {
15070 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15071 }
15072 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015073}
15074
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015075sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015076{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015077 my $Signature = $_[0];
15078 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15079 {
15080 $Signature=~s/\A\Q$ShortName\E\(//g;
15081 cut_f_attrs($Signature);
15082 $Signature=~s/\)\Z//;
15083 return ($ShortName, $Signature);
15084 }
15085
15086 # error
15087 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015088}
15089
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015090sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015091{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015092 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015094 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15095 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015096 foreach my $Pos (0 .. length($Params) - 1)
15097 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015098 my $S = substr($Params, $Pos, 1);
15099 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015100 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015101 }
15102 if($S eq "," and
15103 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015104 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015105 if($Comma)
15106 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015107 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015108 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015109 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015110 }
15111 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015112 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015113 }
15114 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015115 if(not $Sp)
15116 { # remove spaces
15117 foreach (@Parts)
15118 {
15119 s/\A //g;
15120 s/ \Z//g;
15121 }
15122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123 return @Parts;
15124}
15125
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015126sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015127{
15128 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015129 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015131 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15132 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 $Center+=length($1);
15134 }
15135 foreach my $Pos (0 .. length($Sign)-1)
15136 {
15137 my $S = substr($Sign, $Pos, 1);
15138 if($S eq $Target)
15139 {
15140 if($B{"("}==$B{")"}
15141 and $B{"<"}==$B{">"}) {
15142 return $Center;
15143 }
15144 }
15145 if(defined $B{$S}) {
15146 $B{$S}+=1;
15147 }
15148 $Center+=1;
15149 }
15150 return 0;
15151}
15152
15153sub appendFile($$)
15154{
15155 my ($Path, $Content) = @_;
15156 return if(not $Path);
15157 if(my $Dir = get_dirname($Path)) {
15158 mkpath($Dir);
15159 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015160 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015161 print FILE $Content;
15162 close(FILE);
15163}
15164
15165sub writeFile($$)
15166{
15167 my ($Path, $Content) = @_;
15168 return if(not $Path);
15169 if(my $Dir = get_dirname($Path)) {
15170 mkpath($Dir);
15171 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015172 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015173 print FILE $Content;
15174 close(FILE);
15175}
15176
15177sub readFile($)
15178{
15179 my $Path = $_[0];
15180 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015181 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015182 local $/ = undef;
15183 my $Content = <FILE>;
15184 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015185 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015186 $Content=~s/\r/\n/g;
15187 }
15188 return $Content;
15189}
15190
15191sub get_filename($)
15192{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015193 if(defined $Cache{"get_filename"}{$_[0]}) {
15194 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015196 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15197 return ($Cache{"get_filename"}{$_[0]}=$1);
15198 }
15199 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015200}
15201
15202sub get_dirname($)
15203{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015204 if(defined $Cache{"get_dirname"}{$_[0]}) {
15205 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015206 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015207 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15208 return ($Cache{"get_dirname"}{$_[0]}=$1);
15209 }
15210 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015211}
15212
15213sub separate_path($) {
15214 return (get_dirname($_[0]), get_filename($_[0]));
15215}
15216
15217sub esc($)
15218{
15219 my $Str = $_[0];
15220 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15221 return $Str;
15222}
15223
15224sub readLineNum($$)
15225{
15226 my ($Path, $Num) = @_;
15227 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015228 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015229 foreach (1 ... $Num) {
15230 <FILE>;
15231 }
15232 my $Line = <FILE>;
15233 close(FILE);
15234 return $Line;
15235}
15236
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015237sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015239 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 return () if(not $Path or not -f $Path);
15241 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015242 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15243 {
15244 foreach my $AttrVal (split(/;/, $1))
15245 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015246 if($AttrVal=~/(.+):(.+)/)
15247 {
15248 my ($Name, $Value) = ($1, $2);
15249 $Attributes{$Name} = $Value;
15250 }
15251 }
15252 }
15253 return \%Attributes;
15254}
15255
15256sub is_abs($) {
15257 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15258}
15259
15260sub get_abs_path($)
15261{ # abs_path() should NOT be called for absolute inputs
15262 # because it can change them
15263 my $Path = $_[0];
15264 if(not is_abs($Path)) {
15265 $Path = abs_path($Path);
15266 }
15267 return $Path;
15268}
15269
15270sub get_OSgroup()
15271{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015272 my $N = $Config{"osname"};
15273 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274 return "macos";
15275 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015276 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015277 return "bsd";
15278 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015279 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015280 return "beos";
15281 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015282 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015283 return "symbian";
15284 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015285 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015286 return "windows";
15287 }
15288 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015289 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290 }
15291}
15292
15293sub getGccVersion($)
15294{
15295 my $LibVersion = $_[0];
15296 if($GCC_VERSION{$LibVersion})
15297 { # dump version
15298 return $GCC_VERSION{$LibVersion};
15299 }
15300 elsif($UsedDump{$LibVersion}{"V"})
15301 { # old-version dumps
15302 return "unknown";
15303 }
15304 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15305 if(not $GccVersion) {
15306 return "unknown";
15307 }
15308 return $GccVersion;
15309}
15310
15311sub showArch($)
15312{
15313 my $Arch = $_[0];
15314 if($Arch eq "arm"
15315 or $Arch eq "mips") {
15316 return uc($Arch);
15317 }
15318 return $Arch;
15319}
15320
15321sub getArch($)
15322{
15323 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015324
15325 if($TargetArch) {
15326 return $TargetArch;
15327 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015328 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015329 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015330 return $CPU_ARCH{$LibVersion};
15331 }
15332 elsif($UsedDump{$LibVersion}{"V"})
15333 { # old-version dumps
15334 return "unknown";
15335 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015336
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015337 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015338}
15339
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015340sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015341{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015342 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015343
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015344 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015345 if(getArch(1) ne getArch(2)
15346 or getArch(1) eq "unknown"
15347 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348 { # don't show architecture in the header
15349 $ArchInfo="";
15350 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015351 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015352 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015353 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015354 }
15355 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015356 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015357 }
15358 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015359 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015360 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015361
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015362 my $V1 = $Descriptor{1}{"Version"};
15363 my $V2 = $Descriptor{2}{"Version"};
15364
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015365 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15366 {
15367 my $M1 = $UsedDump{1}{"M"};
15368 my $M2 = $UsedDump{2}{"M"};
15369
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015370 my $M1S = $M1;
15371 my $M2S = $M2;
15372
15373 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15374 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15375
15376 if($M1S eq $M2S
15377 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015378 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015379 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15380 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015381 }
15382 else
15383 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015384 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15385 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015386 }
15387 }
15388 else
15389 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015390 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015391 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015392 }
15393
15394 $Title .= $ArchInfo;
15395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015396 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015397 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015399 $Title = "<h1>".$Title."</h1>\n";
15400 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015401}
15402
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015403sub get_CheckedHeaders($)
15404{
15405 my $LibVersion = $_[0];
15406
15407 my @Headers = ();
15408
15409 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15410 {
15411 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015412
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015413 if(not is_target_header($File, $LibVersion)) {
15414 next;
15415 }
15416
15417 if(skipHeader($File, $LibVersion)) {
15418 next;
15419 }
15420
15421 push(@Headers, $Path);
15422 }
15423
15424 return @Headers;
15425}
15426
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015427sub get_SourceInfo()
15428{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015429 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015430
15431 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015432 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015433 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15434 $CheckedHeaders .= "<div class='h_list'>\n";
15435 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 +040015436 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015437 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15438 my $Name = get_filename($Identity);
15439 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15440 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015441 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015442 $CheckedHeaders .= "</div>\n";
15443 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015444 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015445
15446 if(my @Sources = keys(%{$Registered_Sources{1}}))
15447 {
15448 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15449 $CheckedSources .= "<div class='h_list'>\n";
15450 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15451 {
15452 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15453 my $Name = get_filename($Identity);
15454 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15455 $CheckedSources .= $Name.$Comment."<br/>\n";
15456 }
15457 $CheckedSources .= "</div>\n";
15458 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15459 }
15460
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015461 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015462 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015463 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015464 $CheckedLibs .= "<div class='lib_list'>\n";
15465 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15466 {
15467 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15468 $CheckedLibs .= $Library."<br/>\n";
15469 }
15470 $CheckedLibs .= "</div>\n";
15471 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015472 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015473
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015474 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15475}
15476
15477sub get_ObjTitle()
15478{
15479 if(defined $UsedDump{1}{"DWARF"}) {
15480 return "Objects";
15481 }
15482 else {
15483 return ucfirst($SLIB_TYPE)." Libraries";
15484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015485}
15486
15487sub get_TypeProblems_Count($$$)
15488{
15489 my ($TypeChanges, $TargetPriority, $Level) = @_;
15490 my $Type_Problems_Count = 0;
15491 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15492 {
15493 my %Kinds_Target = ();
15494 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15495 {
15496 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15497 {
15498 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015499 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15500 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015501 if($Kinds_Target{$Kind}{$Target}) {
15502 next;
15503 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015504
15505 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15506 {
15507 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15508 { # select a problem with the highest priority
15509 next;
15510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015511 }
15512 $Kinds_Target{$Kind}{$Target} = 1;
15513 $Type_Problems_Count += 1;
15514 }
15515 }
15516 }
15517 return $Type_Problems_Count;
15518}
15519
15520sub get_Summary($)
15521{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015522 my $Level = $_[0];
15523 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015524 $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 +040015525 %{$RESULT{$Level}} = (
15526 "Problems"=>0,
15527 "Warnings"=>0,
15528 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015530 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015531 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015532 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015533 {
15534 if(not defined $CompatRules{$Level}{$Kind})
15535 { # unknown rule
15536 if(not $UnknownRules{$Level}{$Kind})
15537 { # only one warning
15538 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15539 $UnknownRules{$Level}{$Kind}=1;
15540 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015541 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015542 }
15543 }
15544 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015545 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15546 {
15547 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15548 {
15549 if(not defined $CompatRules{$Level}{$Kind})
15550 { # unknown rule
15551 if(not $UnknownRules{$Level}{$Kind})
15552 { # only one warning
15553 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15554 $UnknownRules{$Level}{$Kind}=1;
15555 }
15556 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15557 }
15558 }
15559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015560 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015562 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015563 {
15564 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15565 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015566 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015567 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015568 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015569 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015570 $Added += 1;
15571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015572 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015573 {
15574 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015575 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 }
15577 else
15578 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015579 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 $I_Other += 1;
15581 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015582 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015583 $I_Problems_High += 1;
15584 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015585 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 $I_Problems_Medium += 1;
15587 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015588 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015589 $I_Problems_Low += 1;
15590 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015591 if(($Severity ne "Low" or $StrictCompat)
15592 and $Severity ne "Safe") {
15593 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015594 }
15595 }
15596 }
15597 }
15598 }
15599 }
15600 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015601 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015602 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015603 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015604 {
15605 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15606 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015607 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015608 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015609 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15610 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015611 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015612 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15613
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015614 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 { # select a problem with the highest priority
15616 next;
15617 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015618
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015619 if(($Severity ne "Low" or $StrictCompat)
15620 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015621 {
15622 if(defined $TotalAffected{$Level}{$Interface})
15623 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015624 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15625 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015626 }
15627 }
15628 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015629 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015631 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015632
15633 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15634
15635 if($MaxSeverity)
15636 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015637 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15638 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015639 }
15640 }
15641 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015642 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 }
15645 }
15646 }
15647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015649 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15650 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15651 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15652 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015653
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015654 %TypeChanges = (); # free memory
15655
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015656 # changed and removed public symbols
15657 my $SCount = keys(%{$CheckedSymbols{$Level}});
15658 if($ExtendedCheck)
15659 { # don't count external_func_0 for constants
15660 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015661 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015662 if($SCount)
15663 {
15664 my %Weight = (
15665 "High" => 100,
15666 "Medium" => 50,
15667 "Low" => 25
15668 );
15669 foreach (keys(%{$TotalAffected{$Level}})) {
15670 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015671 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015672 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015674 else {
15675 $RESULT{$Level}{"Affected"} = 0;
15676 }
15677
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015678 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15679 if($RESULT{$Level}{"Affected"}>=100) {
15680 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 }
15682
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015683 $RESULT{$Level}{"Problems"} += $Removed;
15684 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015685 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015686 if($StrictCompat) {
15687 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15688 }
15689 else {
15690 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015693 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015694 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015695 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015696 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015697 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015698 if($Severity eq "Safe")
15699 {
15700 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015701 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015702 elsif($Severity eq "Low")
15703 {
15704 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015705 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015706 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015707 }
15708
15709 if($C_Problems_Low)
15710 {
15711 if($StrictCompat) {
15712 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15713 }
15714 else {
15715 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015716 }
15717 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015718 if($RESULT{$Level}{"Problems"}
15719 and $RESULT{$Level}{"Affected"}) {
15720 $RESULT{$Level}{"Verdict"} = "incompatible";
15721 }
15722 else {
15723 $RESULT{$Level}{"Verdict"} = "compatible";
15724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015725
15726 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15727 if(not $TotalTypes)
15728 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015729 $TotalTypes = keys(%{$TName_Tid{1}});
15730 }
15731
15732 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15733 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15734
15735 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15736
15737 if($ReportFormat eq "xml")
15738 { # XML
15739 # test info
15740 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15741 $TestInfo .= " <version1>\n";
15742 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015743 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015744 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15745 $TestInfo .= " </version1>\n";
15746
15747 $TestInfo .= " <version2>\n";
15748 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015749 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015750 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15751 $TestInfo .= " </version2>\n";
15752 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15753
15754 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015755 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015757 $TestResults .= " <headers>\n";
15758 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15759 {
15760 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15761 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15762 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15763 }
15764 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015765 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015766
15767 if(my @Sources = keys(%{$Registered_Sources{1}}))
15768 {
15769 $TestResults .= " <sources>\n";
15770 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15771 {
15772 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15773 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15774 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15775 }
15776 $TestResults .= " </sources>\n";
15777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015778
15779 $TestResults .= " <libs>\n";
15780 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15781 {
15782 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15783 $TestResults .= " <name>$Library</name>\n";
15784 }
15785 $TestResults .= " </libs>\n";
15786
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015787 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015788 $TestResults .= " <types>".$TotalTypes."</types>\n";
15789
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015790 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15791 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015792 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15793
15794 # problem summary
15795 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15796 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15797
15798 $Problem_Summary .= " <problems_with_types>\n";
15799 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15800 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15801 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15802 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15803 $Problem_Summary .= " </problems_with_types>\n";
15804
15805 $Problem_Summary .= " <problems_with_symbols>\n";
15806 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15807 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15808 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015809 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015810 $Problem_Summary .= " </problems_with_symbols>\n";
15811
15812 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015813 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015814 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015816 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15817
15818 return ($TestInfo.$TestResults.$Problem_Summary, "");
15819 }
15820 else
15821 { # HTML
15822 # test info
15823 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015824 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015825
15826 if($TargetComponent eq "library") {
15827 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
15828 }
15829 else {
15830 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
15831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015832
15833 my (@VInf1, @VInf2, $AddTestInfo) = ();
15834 if($Arch1 ne "unknown"
15835 and $Arch2 ne "unknown")
15836 { # CPU arch
15837 if($Arch1 eq $Arch2)
15838 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015839 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840 }
15841 else
15842 { # go to the version number
15843 push(@VInf1, showArch($Arch1));
15844 push(@VInf2, showArch($Arch2));
15845 }
15846 }
15847 if($GccV1 ne "unknown"
15848 and $GccV2 ne "unknown"
15849 and $OStarget ne "windows")
15850 { # GCC version
15851 if($GccV1 eq $GccV2)
15852 { # go to the separate section
15853 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15854 }
15855 else
15856 { # go to the version number
15857 push(@VInf1, "gcc ".$GccV1);
15858 push(@VInf2, "gcc ".$GccV2);
15859 }
15860 }
15861 # show long version names with GCC version and CPU architecture name (if different)
15862 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15863 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15864 $TestInfo .= $AddTestInfo;
15865 #if($COMMON_LANGUAGE{1}) {
15866 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15867 #}
15868 if($ExtendedCheck) {
15869 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 if($JoinReport)
15872 {
15873 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015874 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015875 }
15876 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015877 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015878 }
15879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015880 $TestInfo .= "</table>\n";
15881
15882 # test results
15883 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015884 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015885
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015886 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015887 {
15888 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15889 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15890 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015891
15892 if(my @Sources = keys(%{$Registered_Sources{1}}))
15893 {
15894 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15895 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015897
15898 if(not $ExtendedCheck)
15899 {
15900 my $Libs_Link = "0";
15901 $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 +040015902 $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 +040015903 }
15904
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015905 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015906
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015907 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908 if($JoinReport) {
15909 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15910 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015911 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015912 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015913 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15914 }
15915 else {
15916 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15917 }
15918 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015919 $TestResults .= "</table>\n";
15920
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015921 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015922 # problem summary
15923 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015924 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015925 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15926
15927 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015928 if($Added>0)
15929 {
15930 if($JoinReport) {
15931 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15932 }
15933 else {
15934 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15935 }
15936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015937 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015938 $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 +040015939
15940 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015941 if($Removed>0)
15942 {
15943 if($JoinReport) {
15944 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15945 }
15946 else {
15947 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15948 }
15949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015950 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015951 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15952 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015953
15954 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015955 $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 +040015956 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015957 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15958 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015959
15960 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015961 $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 +040015962 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015963 $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 +040015964
15965 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015966 $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 +040015967 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015968 $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 +040015969
15970 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015971 $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 +040015972 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015973 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15974 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015975
15976 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015977 $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 +040015978 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015979 $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 +040015980
15981 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015982 $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 +040015983 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015984 $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 +040015985
15986 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015987 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15988 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015989 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015990 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015991 $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 +040015992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015994 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 {
15996 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015997 $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 +030015998 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015999 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016000
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016001 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016002 {
16003 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016004 $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 +030016005 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016007
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016008 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016009 {
16010 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16011 $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 +030016012 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016013 }
16014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 $META_DATA .= "tool_version:$TOOL_VERSION";
16016 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016017 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016018 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16019 }
16020}
16021
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016022sub getStyle($$$)
16023{
16024 my ($Subj, $Act, $Num) = @_;
16025 my %Style = (
16026 "A"=>"new",
16027 "R"=>"failed",
16028 "S"=>"passed",
16029 "L"=>"warning",
16030 "M"=>"failed",
16031 "H"=>"failed"
16032 );
16033 if($Num>0) {
16034 return " class='".$Style{$Act}."'";
16035 }
16036 return "";
16037}
16038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016039sub show_number($)
16040{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016041 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016042 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016043 my $Num = cut_off_number($_[0], 2, 0);
16044 if($Num eq "0")
16045 {
16046 foreach my $P (3 .. 7)
16047 {
16048 $Num = cut_off_number($_[0], $P, 1);
16049 if($Num ne "0") {
16050 last;
16051 }
16052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016053 }
16054 if($Num eq "0") {
16055 $Num = $_[0];
16056 }
16057 return $Num;
16058 }
16059 return $_[0];
16060}
16061
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016062sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016064 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016065 if($num!~/\./)
16066 {
16067 $num .= ".";
16068 foreach (1 .. $digs_to_cut-1) {
16069 $num .= "0";
16070 }
16071 }
16072 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16073 {
16074 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16075 $num .= "0";
16076 }
16077 }
16078 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16079 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16080 }
16081 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 if($z) {
16083 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016085 return $num;
16086}
16087
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016088sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016089{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016090 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016091 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016092
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016093 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016094 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16095 {
16096 my $Header = $Constants{1}{$Constant}{"Header"};
16097 if(not $Header)
16098 { # added
16099 $Header = $Constants{2}{$Constant}{"Header"}
16100 }
16101
16102 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16103 {
16104 if(not defined $CompatRules{$Level}{$Kind}) {
16105 next;
16106 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016107 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016108 next;
16109 }
16110 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016112 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016113
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016114 if($ReportFormat eq "xml")
16115 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016116 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016117 {
16118 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016119 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016120 {
16121 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016122 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16123 {
16124 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16125 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16126 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016127
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016128 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16129 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16130 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016131 if($Overcome) {
16132 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16133 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016134 $CHANGED_CONSTANTS .= " </problem>\n";
16135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016136 $CHANGED_CONSTANTS .= " </constant>\n";
16137 }
16138 $CHANGED_CONSTANTS .= " </header>\n";
16139 }
16140 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16141 }
16142 else
16143 { # HTML
16144 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016145 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146 {
16147 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016148 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016150 my $Report = "";
16151
16152 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16153 {
16154 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16155 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016156 $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 +040016157 $Number += 1;
16158 }
16159 if($Report)
16160 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016161 $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 +040016162 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16163 $Report = insertIDs($Report);
16164 }
16165 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016166 }
16167 $CHANGED_CONSTANTS .= "<br/>\n";
16168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016169 if($CHANGED_CONSTANTS)
16170 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016171 my $Title = "Problems with Constants, $TargetSeverity Severity";
16172 if($TargetSeverity eq "Safe")
16173 { # Safe Changes
16174 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016175 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016176 $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 +040016177 }
16178 }
16179 return $CHANGED_CONSTANTS;
16180}
16181
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016182sub getTitle($$$)
16183{
16184 my ($Header, $Library, $NameSpace) = @_;
16185 my $Title = "";
16186 if($Library and $Library!~/\.\w+\Z/) {
16187 $Library .= " (.$LIB_EXT)";
16188 }
16189 if($Header and $Library)
16190 {
16191 $Title .= "<span class='h_name'>$Header</span>";
16192 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16193 }
16194 elsif($Library) {
16195 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16196 }
16197 elsif($Header) {
16198 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16199 }
16200 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016201 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016202 }
16203 return $Title;
16204}
16205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016206sub get_Report_Added($)
16207{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016208 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016209 my $ADDED_INTERFACES = "";
16210 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016211 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016212 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016213 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016214 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216 {
16217 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16218 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016219 if($Level eq "Source" and $ReportFormat eq "html")
16220 { # do not show library name in HTML report
16221 $DyLib = "";
16222 }
16223 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 }
16225 }
16226 }
16227 if($ReportFormat eq "xml")
16228 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230 {
16231 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016232 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016233 {
16234 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016235 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016236 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16237 }
16238 $ADDED_INTERFACES .= " </library>\n";
16239 }
16240 $ADDED_INTERFACES .= " </header>\n";
16241 }
16242 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16243 }
16244 else
16245 { # HTML
16246 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016247 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016249 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016250 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 my %NameSpaceSymbols = ();
16252 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016253 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016255 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016256 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016257 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16258 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259 foreach my $Interface (@SortedInterfaces)
16260 {
16261 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016262 my $Signature = get_Signature($Interface, 2);
16263 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016264 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016265 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016266 if($Interface=~/\A(_Z|\?)/)
16267 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016269 $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 +040016270 }
16271 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016272 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 }
16274 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016275 else
16276 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016277 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016278 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 }
16280 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016281 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016282 }
16283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016285 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 }
16288 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016289 if($ADDED_INTERFACES)
16290 {
16291 my $Anchor = "<a name='Added'></a>";
16292 if($JoinReport) {
16293 $Anchor = "<a name='".$Level."_Added'></a>";
16294 }
16295 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016296 }
16297 }
16298 return $ADDED_INTERFACES;
16299}
16300
16301sub get_Report_Removed($)
16302{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016303 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016304 my $REMOVED_INTERFACES = "";
16305 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016306 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016307 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016308 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016309 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016310 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016312 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16313 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016314 if($Level eq "Source" and $ReportFormat eq "html")
16315 { # do not show library name in HTML report
16316 $DyLib = "";
16317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016318 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016319 }
16320 }
16321 }
16322 if($ReportFormat eq "xml")
16323 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016324 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016325 {
16326 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016327 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016328 {
16329 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016330 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16331 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016332 }
16333 $REMOVED_INTERFACES .= " </library>\n";
16334 }
16335 $REMOVED_INTERFACES .= " </header>\n";
16336 }
16337 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16338 }
16339 else
16340 { # HTML
16341 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016342 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016344 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 my %NameSpaceSymbols = ();
16347 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016348 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016349 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016350 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016352 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16353 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016354 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355 {
16356 $Removed_Number += 1;
16357 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016358 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016359 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016360 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016362 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016363 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016365 $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 +040016366 }
16367 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016368 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016369 }
16370 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016371 else
16372 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016373 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016374 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 }
16376 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016377 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016378 }
16379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 }
16381 }
16382 $REMOVED_INTERFACES .= "<br/>\n";
16383 }
16384 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016385 if($REMOVED_INTERFACES)
16386 {
16387 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16388 if($JoinReport) {
16389 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16390 }
16391 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016392 }
16393 }
16394 return $REMOVED_INTERFACES;
16395}
16396
16397sub getXmlParams($$)
16398{
16399 my ($Content, $Problem) = @_;
16400 return "" if(not $Content or not $Problem);
16401 my %XMLparams = ();
16402 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16403 {
16404 my $Macro = "\@".lc($Attr);
16405 if($Content=~/\Q$Macro\E/) {
16406 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16407 }
16408 }
16409 my @PString = ();
16410 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016411 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016412 }
16413 if(@PString) {
16414 return " ".join(" ", @PString);
16415 }
16416 else {
16417 return "";
16418 }
16419}
16420
16421sub addMarkup($)
16422{
16423 my $Content = $_[0];
16424 # auto-markup
16425 $Content=~s/\n[ ]*//; # spaces
16426 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16427 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016428 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016429 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16430 if($Content=~/\ANOTE:/)
16431 { # notes
16432 $Content=~s!(NOTE):!<b>$1</b>:!g;
16433 }
16434 else {
16435 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16436 }
16437 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16438 my @Keywords = (
16439 "void",
16440 "const",
16441 "static",
16442 "restrict",
16443 "volatile",
16444 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016445 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016446 );
16447 my $MKeys = join("|", @Keywords);
16448 foreach (@Keywords) {
16449 $MKeys .= "|non-".$_;
16450 }
16451 $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 +040016452
16453 # Markdown
16454 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16455 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016456 return $Content;
16457}
16458
16459sub applyMacroses($$$$)
16460{
16461 my ($Level, $Kind, $Content, $Problem) = @_;
16462 return "" if(not $Content or not $Problem);
16463 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16464 $Content = addMarkup($Content);
16465 # macros
16466 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16467 {
16468 my $Macro = "\@".lc($Attr);
16469 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016470 if(not defined $Value
16471 or $Value eq "") {
16472 next;
16473 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016474
16475 if(index($Content, $Macro)==-1) {
16476 next;
16477 }
16478
16479 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16480 and $Kind!~/_Type_/
16481 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016482 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016484 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 $Value = black_name($Value);
16486 }
16487 elsif($Value=~/\s/) {
16488 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16489 }
16490 elsif($Value=~/\A\d+\Z/
16491 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16492 { # bits to bytes
16493 if($Value % $BYTE_SIZE)
16494 { # bits
16495 if($Value==1) {
16496 $Value = "<b>".$Value."</b> bit";
16497 }
16498 else {
16499 $Value = "<b>".$Value."</b> bits";
16500 }
16501 }
16502 else
16503 { # bytes
16504 $Value /= $BYTE_SIZE;
16505 if($Value==1) {
16506 $Value = "<b>".$Value."</b> byte";
16507 }
16508 else {
16509 $Value = "<b>".$Value."</b> bytes";
16510 }
16511 }
16512 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016513 else
16514 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016515 $Value = "<b>".htmlSpecChars($Value)."</b>";
16516 }
16517 $Content=~s/\Q$Macro\E/$Value/g;
16518 }
16519
16520 if($Content=~/(\A|[^\@\w])\@\w/)
16521 {
16522 if(not $IncompleteRules{$Level}{$Kind})
16523 { # only one warning
16524 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16525 $IncompleteRules{$Level}{$Kind} = 1;
16526 }
16527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 return $Content;
16529}
16530
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016531sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016532{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016533 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016534 my $INTERFACE_PROBLEMS = "";
16535 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016536
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016537 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016538 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16540 if($SV and defined $CompatProblems{$Level}{$SN}) {
16541 next;
16542 }
16543 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 {
16545 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016546 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016547 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16549 my $DyLib = $Symbol_Library{1}{$Symbol};
16550 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016551 { # Symbol with Version
16552 $DyLib = $Symbol_Library{1}{$VSym};
16553 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016554 if(not $DyLib)
16555 { # const global data
16556 $DyLib = "";
16557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016558 if($Level eq "Source" and $ReportFormat eq "html")
16559 { # do not show library name in HTML report
16560 $DyLib = "";
16561 }
16562 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16563 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016565 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16566 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016567 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 }
16569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16571 {
16572 delete($SymbolChanges{$Symbol}{$Kind});
16573 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 }
16577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016578 if(not keys(%{$SymbolChanges{$Symbol}})) {
16579 delete($SymbolChanges{$Symbol});
16580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016582
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016583 if($ReportFormat eq "xml")
16584 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 {
16587 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016588 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016589 {
16590 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016591 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16592 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016593 {
16594 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16595 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16596 {
16597 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16598 {
16599 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016600 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016601
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016602 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16603 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16604 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16605 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16606 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016607 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16608 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016610 $INTERFACE_PROBLEMS .= " </problem>\n";
16611 }
16612 }
16613 $INTERFACE_PROBLEMS .= " </symbol>\n";
16614 }
16615 $INTERFACE_PROBLEMS .= " </library>\n";
16616 }
16617 $INTERFACE_PROBLEMS .= " </header>\n";
16618 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016619 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 }
16621 else
16622 { # HTML
16623 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016624 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016626 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016628 my (%NameSpaceSymbols, %NewSignature) = ();
16629 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016630 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016631 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016632 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016633 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016635 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 +040016636 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016638 my $Signature = get_Signature($Symbol, 1);
16639 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016640 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016641 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016645 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016646 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016647 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016648 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 }
16650 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16651 {
16652 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016653 $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 +040016654 $ProblemNum += 1;
16655 $ProblemsNum += 1;
16656 }
16657 }
16658 }
16659 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016660 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016663 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016664 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 }
16666 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016667 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016668 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016669 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16670 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16671 if($NewSignature{$Symbol})
16672 { # argument list changed to
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016673 $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 +040016674 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016675 if($Symbol=~/\A(_Z|\?)/) {
16676 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16677 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016678 $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 +040016679 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016681 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 }
16683 }
16684 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016685 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016686 }
16687 }
16688 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016689
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016690 if($INTERFACE_PROBLEMS)
16691 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016692 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16693 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16694 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016695 { # Safe Changes
16696 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016697 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016698 $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 +040016699 }
16700 }
16701 return $INTERFACE_PROBLEMS;
16702}
16703
16704sub get_Report_TypeProblems($$)
16705{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016706 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016707 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016708 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016709
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016710 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016711 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016712 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016713 {
16714 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16715 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016716 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016717 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016719 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016720 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016721
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 if($Severity eq "Safe"
16723 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724 next;
16725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016726
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016727 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16728 {
16729 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16730 { # select a problem with the highest priority
16731 next;
16732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016733 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016734
16735 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016736 }
16737 }
16738 }
16739 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016740
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016741 my %Kinds_Locations = ();
16742 foreach my $TypeName (keys(%TypeChanges))
16743 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016744 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16746 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016747 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016749 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016750 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016751 { # other priority
16752 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16753 next;
16754 }
16755 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16756 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016757 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 { # duplicate target
16759 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16760 next;
16761 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016762 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016763 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016764 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 }
16766 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16767 delete($TypeChanges{$TypeName}{$Kind});
16768 }
16769 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016770 if(not keys(%{$TypeChanges{$TypeName}})) {
16771 delete($TypeChanges{$TypeName});
16772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016773 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016774
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016775 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 +040016776 if($ReportFormat eq "xml")
16777 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016779 {
16780 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016781 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016782 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016783 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16785 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016786 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016787 {
16788 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16789 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16790 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16791 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16792 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16793 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016794 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16795 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16796 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016797 $TYPE_PROBLEMS .= " </problem>\n";
16798 }
16799 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016800 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016801 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802 $TYPE_PROBLEMS .= showVTables($TypeName);
16803 }
16804 $TYPE_PROBLEMS .= " </type>\n";
16805 }
16806 $TYPE_PROBLEMS .= " </header>\n";
16807 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016808 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 }
16810 else
16811 { # HTML
16812 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016815 my (%NameSpace_Type) = ();
16816 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016817 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016818 }
16819 foreach my $NameSpace (sort keys(%NameSpace_Type))
16820 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016821 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016822 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 +040016823 foreach my $TypeName (@SortedTypes)
16824 {
16825 my $ProblemNum = 1;
16826 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16829 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016830 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016831 {
16832 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16833 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16834 {
16835 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016836 $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 +040016837 $ProblemNum += 1;
16838 $ProblemsNum += 1;
16839 }
16840 }
16841 }
16842 $ProblemNum -= 1;
16843 if($TYPE_REPORT)
16844 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016845 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016847 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016848 $ShowVTables = showVTables($TypeName);
16849 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016850
16851 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016852 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16853 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16854 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16855 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016857 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016858 }
16859 }
16860 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016861 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 }
16863 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016865 if($TYPE_PROBLEMS)
16866 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016867 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16868 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 { # Safe Changes
16871 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016873 $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 +040016874 }
16875 }
16876 return $TYPE_PROBLEMS;
16877}
16878
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016879sub show_Type($$$)
16880{
16881 my ($Name, $Html, $LibVersion) = @_;
16882 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16883 $TType = lc($TType);
16884 if($TType=~/struct|union|enum/) {
16885 $Name=~s/\A\Q$TType\E //g;
16886 }
16887 if($Html) {
16888 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16889 }
16890 else {
16891 $Name = $TType." ".$Name;
16892 }
16893 return $Name;
16894}
16895
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016896sub get_Anchor($$$)
16897{
16898 my ($Kind, $Level, $Severity) = @_;
16899 if($JoinReport)
16900 {
16901 if($Severity eq "Safe") {
16902 return "Other_".$Level."_Changes_In_".$Kind."s";
16903 }
16904 else {
16905 return $Kind."_".$Level."_Problems_".$Severity;
16906 }
16907 }
16908 else
16909 {
16910 if($Severity eq "Safe") {
16911 return "Other_Changes_In_".$Kind."s";
16912 }
16913 else {
16914 return $Kind."_Problems_".$Severity;
16915 }
16916 }
16917}
16918
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016919sub showVTables($)
16920{
16921 my $TypeName = $_[0];
16922 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016923 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016924 if(defined $Type1{"VTable"}
16925 and keys(%{$Type1{"VTable"}}))
16926 {
16927 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016928 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016929 if(defined $Type2{"VTable"}
16930 and keys(%{$Type2{"VTable"}}))
16931 {
16932 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16933 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016934 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16937 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016938 }
16939 my $VTABLES = "";
16940 if($ReportFormat eq "xml")
16941 { # XML
16942 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016943 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016945 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016946 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16947 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016948 $VTABLES .= " </entry>\n";
16949 }
16950 $VTABLES .= " </vtable>\n\n";
16951 }
16952 else
16953 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016954 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016955 $VTABLES .= "<tr><th>Offset</th>";
16956 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016958 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016959 {
16960 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016961 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016963 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016965 $Color1 = " class='failed'";
16966 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 }
16968 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016969 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016970 }
16971 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016972 $VTABLES .= "<tr><th>".$Index."</th>\n";
16973 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16974 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 }
16976 $VTABLES .= "</table><br/>\n";
16977 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016978 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 }
16980 return $VTABLES;
16981 }
16982 }
16983 return "";
16984}
16985
16986sub simpleVEntry($)
16987{
16988 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016989 if(not defined $VEntry
16990 or $VEntry eq "") {
16991 return "";
16992 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016993
16994 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016995 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16996 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16997 if($VEntry=~/\A_ZThn.+\Z/) {
16998 $VEntry = "non-virtual thunk";
16999 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017000 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017001 # support for old GCC versions
17002 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17003 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17004 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17006 return $VEntry;
17007}
17008
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017009sub adjustParamPos($$$)
17010{
17011 my ($Pos, $Symbol, $LibVersion) = @_;
17012 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17013 {
17014 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17015 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17016 {
17017 return $Pos-1;
17018 }
17019
17020 return $Pos;
17021 }
17022
17023 return undef;
17024}
17025
17026sub getParamPos($$$)
17027{
17028 my ($Name, $Symbol, $LibVersion) = @_;
17029
17030 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17031 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17032 {
17033 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17034 foreach (keys(%{$Info->{"Param"}}))
17035 {
17036 if($Info->{"Param"}{$_}{"name"} eq $Name)
17037 {
17038 return $_;
17039 }
17040 }
17041 }
17042
17043 return undef;
17044}
17045
17046sub getParamName($)
17047{
17048 my $Loc = $_[0];
17049 $Loc=~s/\->.*//g;
17050 return $Loc;
17051}
17052
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017053sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017054{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017055 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017056 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017057
17058 if(defined $AffectLimit)
17059 {
17060 $LIMIT = $AffectLimit;
17061 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017062
17063 my %SymSel = ();
17064 my %SymLocKind = ();
17065
17066 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017068 if(index($Symbol, "_Z")==0
17069 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017070 { # duplicated problems for C2 constructors, D2 and D0 destructors
17071 next;
17072 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017073
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017074 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017075 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017076 if(not defined $CompatProblems{$Level}{$Symbol}
17077 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17078 next;
17079 }
17080
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017081 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017083 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017084 next;
17085 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017086
17087 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17088 if($Level eq "Source")
17089 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017090 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017091 }
17092
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017093 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017094 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017095 { # duplicated problems for versioned symbols
17096 next;
17097 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017098
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017099 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017100 if($Type_Name ne $Target_TypeName) {
17101 next;
17102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017103
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017104 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 }
17106 }
17107 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017108
17109 foreach my $Symbol (sort keys(%SymLocKind))
17110 {
17111 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17112 {
17113 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17114 {
17115 $SymSel{$Symbol}{"Loc"} = $Loc;
17116 $SymSel{$Symbol}{"Kind"} = $Kind;
17117
17118 last LOOP;
17119 }
17120 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017121 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017124 my $Num = 0;
17125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 if($ReportFormat eq "xml")
17127 { # XML
17128 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017129
17130 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017132 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017133 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017134 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017135
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017136 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017137 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017138 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017139 $Target .= " param=\"$PName\"";
17140 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017142 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017143 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017144 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017145 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017146 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017147 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017148
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017149 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017150 $Target .= " field=\"$1\"";
17151 }
17152
17153 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017154 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017156
17157 if($Num>$LIMIT) {
17158 last LOOP;
17159 }
17160
17161 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017162 }
17163 $Affected .= " </affected>\n";
17164 }
17165 else
17166 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017167 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017168 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017169 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17170 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017171 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017172 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17173
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017174 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017175 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17176
17177 if($Num>$LIMIT) {
17178 last;
17179 }
17180
17181 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017182 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017183
17184 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017185 $Affected .= " ...\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017186 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017187
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017188 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017189 if($Affected)
17190 {
17191 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017192 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017193 }
17194 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017196 return $Affected;
17197}
17198
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017199sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017200{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017201 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017202 if($L2=~/\A(retval|this)\b/
17203 and $L1!~/\A(retval|this)\b/)
17204 {
17205 if($L1!~/\-\>/) {
17206 return 1;
17207 }
17208 elsif($L2=~/\-\>/) {
17209 return 1;
17210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 }
17212 return 0;
17213}
17214
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017215sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017216{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017217 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017218
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017219 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017220
17221 my $Location_I = $Location;
17222 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017224 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017226 if($Kind eq "Overridden_Virtual_Method"
17227 or $Kind eq "Overridden_Virtual_Method_B") {
17228 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17229 }
17230 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17231 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017232 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17235 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017236 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17237 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17238
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239 if($ClassName eq $Problem{"Type_Name"}) {
17240 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17241 }
17242 else {
17243 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17244 }
17245 }
17246 else
17247 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017248 my $TypeID = undef;
17249
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017250 if($Location=~/retval/)
17251 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017252 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017253 push(@Sentence, "Field \'".$Location."\' in return value");
17254 }
17255 else {
17256 push(@Sentence, "Return value");
17257 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017258
17259 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 }
17261 elsif($Location=~/this/)
17262 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017263 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017264 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17265 }
17266 else {
17267 push(@Sentence, "\'this\' pointer");
17268 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017269
17270 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017271 }
17272 else
17273 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017274
17275 my $PName = getParamName($Location);
17276 my $PPos = getParamPos($PName, $Symbol, 1);
17277
17278 if(index($Location, "->")!=-1) {
17279 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017280 }
17281 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017282 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017283 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017284 if($PName) {
17285 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017286 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017287
17288 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17289 }
17290
17291 if($Location!~/this/)
17292 {
17293 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017294 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017295 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017296 push(@Sentence, "(pointer)");
17297 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017298 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017299 push(@Sentence, "(reference)");
17300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301 }
17302 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017303
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017304 if($Location eq "this") {
17305 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17306 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017307 else
17308 {
17309 my $Location_T = $Location;
17310 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17311
17312 my $TypeID_Problem = $TypeID;
17313 if($Location_T) {
17314 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17315 }
17316
17317 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17318 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17319 }
17320 else {
17321 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 }
17324 }
17325 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017326 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017327 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 +040017328 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017329
17330 my $Sent = join(" ", @Sentence);
17331
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017332 $Sent=~s/->/./g;
17333
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017334 if($ReportFormat eq "xml")
17335 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017336 $Sent=~s/'//g;
17337 }
17338
17339 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017340}
17341
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017342sub getFieldType($$$)
17343{
17344 my ($Location, $TypeId, $LibVersion) = @_;
17345
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017346 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017347
17348 foreach my $Name (@Fields)
17349 {
17350 my %Info = get_BaseType($TypeId, $LibVersion);
17351
17352 foreach my $Pos (keys(%{$Info{"Memb"}}))
17353 {
17354 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17355 {
17356 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17357 last;
17358 }
17359 }
17360 }
17361
17362 return $TypeId;
17363}
17364
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017365sub get_XmlSign($$)
17366{
17367 my ($Symbol, $LibVersion) = @_;
17368 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17369 my $Report = "";
17370 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17371 {
17372 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017373 my $Type = $Info->{"Param"}{$Pos}{"type"};
17374 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017375 foreach my $Typedef (keys(%ChangedTypedef))
17376 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017377 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17378 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 }
17381 $Report .= " <param pos=\"$Pos\">\n";
17382 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017383 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017384 $Report .= " </param>\n";
17385 }
17386 if(my $Return = $Info->{"Return"})
17387 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017388 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017389 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017390 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 $Report .= " </retval>\n";
17392 }
17393 return $Report;
17394}
17395
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017396sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017397{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017398 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017399 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017400 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017402 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17403 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017404 next;
17405 }
17406 $Report .= " <symbol name=\"$Symbol\">\n";
17407 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017408 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017409 {
17410 if(defined $CompleteSignature{1}{$Symbol}
17411 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17412 {
17413 $P1 = get_XmlSign($Symbol, 1);
17414 $S1 = get_Signature($Symbol, 1);
17415 }
17416 elsif($Symbol=~/\A(_Z|\?)/) {
17417 $S1 = $tr_name{$Symbol};
17418 }
17419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017420 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017421 {
17422 if(defined $CompleteSignature{2}{$Symbol}
17423 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17424 {
17425 $P2 = get_XmlSign($Symbol, 2);
17426 $S2 = get_Signature($Symbol, 2);
17427 }
17428 elsif($Symbol=~/\A(_Z|\?)/) {
17429 $S2 = $tr_name{$Symbol};
17430 }
17431 }
17432 if($S1)
17433 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017434 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435 $Report .= $P1;
17436 $Report .= " </old>\n";
17437 }
17438 if($S2 and $S2 ne $S1)
17439 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017440 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017441 $Report .= $P2;
17442 $Report .= " </new>\n";
17443 }
17444 $Report .= " </symbol>\n";
17445 }
17446 $Report .= "</symbols_info>\n";
17447 return $Report;
17448}
17449
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017450sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017451{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017452 my ($Level, $Report) = @_;
17453 if($ReportFormat eq "xml") {
17454 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017455 }
17456 if($StdOut)
17457 { # --stdout option
17458 print STDOUT $Report;
17459 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017460 else
17461 {
17462 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017463 mkpath(get_dirname($RPath));
17464
17465 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17466 print REPORT $Report;
17467 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017468 }
17469}
17470
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017471sub getReport($)
17472{
17473 my $Level = $_[0];
17474 if($ReportFormat eq "xml")
17475 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017476 if($Level eq "Join")
17477 {
17478 my $Report = "<reports>\n";
17479 $Report .= getReport("Binary");
17480 $Report .= getReport("Source");
17481 $Report .= "</reports>\n";
17482 return $Report;
17483 }
17484 else
17485 {
17486 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17487 my ($Summary, $MetaData) = get_Summary($Level);
17488 $Report .= $Summary."\n";
17489 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17490 $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 +040017491
17492 # additional symbols info (if needed)
17493 # $Report .= get_Report_SymbolsInfo($Level);
17494
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017495 $Report .= "</report>\n";
17496 return $Report;
17497 }
17498 }
17499 else
17500 { # HTML
17501 my $CssStyles = readModule("Styles", "Report.css");
17502 my $JScripts = readModule("Scripts", "Sections.js");
17503 if($Level eq "Join")
17504 {
17505 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17506 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017507 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017508 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17509 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 +040017510 my ($BSummary, $BMetaData) = get_Summary("Binary");
17511 my ($SSummary, $SMetaData) = get_Summary("Source");
17512 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 +030017513 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017514 <br/>
17515 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017516 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17517 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017518 </div>";
17519 $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>";
17520 $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 +030017521 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017522 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017523 return $Report;
17524 }
17525 else
17526 {
17527 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017528 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17529 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17530 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 +040017531 if($Level eq "Binary")
17532 {
17533 if(getArch(1) eq getArch(2)
17534 and getArch(1) ne "unknown") {
17535 $Description .= " on ".showArch(getArch(1));
17536 }
17537 }
17538 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 +030017539 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017540 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17541 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17542 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017543 $Report .= "</div>\n<br/><br/><br/>\n";
17544 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017545 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017546 return $Report;
17547 }
17548 }
17549}
17550
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017551sub getLegend()
17552{
17553 return "<br/>
17554<table class='summary'>
17555<tr>
17556 <td class='new'>added</td>
17557 <td class='passed'>compatible</td>
17558</tr>
17559<tr>
17560 <td class='warning'>warning</td>
17561 <td class='failed'>incompatible</td>
17562</tr></table>\n";
17563}
17564
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017565sub createReport()
17566{
17567 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017568 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017569 writeReport("Join", getReport("Join"));
17570 }
17571 elsif($DoubleReport)
17572 { # default
17573 writeReport("Binary", getReport("Binary"));
17574 writeReport("Source", getReport("Source"));
17575 }
17576 elsif($BinaryOnly)
17577 { # --binary
17578 writeReport("Binary", getReport("Binary"));
17579 }
17580 elsif($SourceOnly)
17581 { # --source
17582 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017583 }
17584}
17585
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017586sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017587{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017588 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017589
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017590 $Footer .= "<hr/>";
17591 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017592 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017593 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017594 $Footer .= "<br/>\n";
17595
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017596 return $Footer;
17597}
17598
17599sub get_Report_Problems($$)
17600{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017601 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017602
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017603 my $Report = get_Report_TypeProblems($Severity, $Level);
17604 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017605 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017606 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017607
17608 if($Severity eq "Low" or $Severity eq "Safe") {
17609 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017610 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017611
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017612 if($ReportFormat eq "html")
17613 {
17614 if($Report)
17615 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017616 if($JoinReport)
17617 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017618 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017619 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17620 }
17621 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017622 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017624 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017625 else
17626 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017627 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017628 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17629 }
17630 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017631 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017633 }
17634 }
17635 }
17636 return $Report;
17637}
17638
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017639sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017640{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017641 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17642 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17643 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17644 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017645 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17646 <meta name=\"keywords\" content=\"$Keywords\" />
17647 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017648 <title>
17649 $Title
17650 </title>
17651 <style type=\"text/css\">
17652 $Styles
17653 </style>
17654 <script type=\"text/javascript\" language=\"JavaScript\">
17655 <!--
17656 $Scripts
17657 -->
17658 </script>
17659 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017660}
17661
17662sub insertIDs($)
17663{
17664 my $Text = $_[0];
17665 while($Text=~/CONTENT_ID/)
17666 {
17667 if(int($Content_Counter)%2) {
17668 $ContentID -= 1;
17669 }
17670 $Text=~s/CONTENT_ID/c_$ContentID/;
17671 $ContentID += 1;
17672 $Content_Counter += 1;
17673 }
17674 return $Text;
17675}
17676
17677sub checkPreprocessedUnit($)
17678{
17679 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017680 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017681 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017682 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017683
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017684 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017685 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017686 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017687 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017688 chomp($Line);
17689 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017690 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017691 $CurHeader = path_format($1, $OSgroup);
17692 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017693 $CurClass = "";
17694
17695 if(index($CurHeader, $TMP_DIR)==0) {
17696 next;
17697 }
17698
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017699 if(substr($CurHeaderName, 0, 1) eq "<")
17700 { # <built-in>, <command-line>, etc.
17701 $CurHeaderName = "";
17702 $CurHeader = "";
17703 }
17704
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017705 if($ExtraInfo)
17706 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017707 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017708 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17709 }
17710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017711 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017712 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017713 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017714 if($CurHeaderName)
17715 {
17716 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17717 and not $Registered_Headers{$Version}{$CurHeader})
17718 { # not a target
17719 next;
17720 }
17721 if(not is_target_header($CurHeaderName, 1)
17722 and not is_target_header($CurHeaderName, 2))
17723 { # user-defined header
17724 next;
17725 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017726 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017727 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017728
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017729 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017730 {
17731 my ($Name, $Value) = ($1, $2);
17732 if(not $Constants{$Version}{$Name}{"Access"})
17733 {
17734 $Constants{$Version}{$Name}{"Access"} = "public";
17735 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017736 if($CurHeaderName) {
17737 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17738 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017739 }
17740 }
17741 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17742 $Constants{$Version}{$1}{"Access"} = "private";
17743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017744 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017745 else
17746 {
17747 if(defined $ExtraDump)
17748 {
17749 if($Line=~/(\w+)\s*\(/)
17750 { # functions
17751 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17752 }
17753 #elsif($Line=~/(\w+)\s*;/)
17754 #{ # data
17755 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17756 #}
17757 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17758 $CurClass = $2;
17759 }
17760 }
17761 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017762 }
17763 close(PREPROC);
17764 foreach my $Constant (keys(%{$Constants{$Version}}))
17765 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017766 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17767 {
17768 delete($Constants{$Version}{$Constant});
17769 next;
17770 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017771 if(not $ExtraDump and ($Constant=~/_h\Z/i
17772 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017773 { # skip
17774 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017775 }
17776 else {
17777 delete($Constants{$Version}{$Constant}{"Access"});
17778 }
17779 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017780 if($Debug)
17781 {
17782 mkpath($DEBUG_PATH{$Version});
17783 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017785}
17786
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017787sub uncoverConstant($$)
17788{
17789 my ($LibVersion, $Constant) = @_;
17790 return "" if(not $LibVersion or not $Constant);
17791 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17792 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17793 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17794 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017795
17796 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017797 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017798 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17799 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017800 {
17801 push(@RecurConstant, $Constant);
17802 my $Uncovered = uncoverConstant($LibVersion, $Value);
17803 if($Uncovered ne "") {
17804 $Value = $Uncovered;
17805 }
17806 pop(@RecurConstant);
17807 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017808
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017809 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017810 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017811 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17812 }
17813 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17814}
17815
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017816sub simpleConstant($$)
17817{
17818 my ($LibVersion, $Value) = @_;
17819 if($Value=~/\W/)
17820 {
17821 my $Value_Copy = $Value;
17822 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17823 {
17824 my $Word = $1;
17825 if($Value!~/$Word\s*\(/)
17826 {
17827 my $Val = uncoverConstant($LibVersion, $Word);
17828 if($Val ne "")
17829 {
17830 $Value=~s/\b$Word\b/$Val/g;
17831 }
17832 }
17833 }
17834 }
17835 return $Value;
17836}
17837
17838sub computeValue($)
17839{
17840 my $Value = $_[0];
17841
17842 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17843 return $1;
17844 }
17845
17846 if($Value=~/\A[\d\-\+()]+\Z/) {
17847 return eval($Value);
17848 }
17849
17850 return $Value;
17851}
17852
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017853my %IgnoreConstant = map {$_=>1} (
17854 "VERSION",
17855 "VERSIONCODE",
17856 "VERNUM",
17857 "VERS_INFO",
17858 "PATCHLEVEL",
17859 "INSTALLPREFIX",
17860 "VBUILD",
17861 "VPATCH",
17862 "VMINOR",
17863 "BUILD_STRING",
17864 "BUILD_TIME",
17865 "PACKAGE_STRING",
17866 "PRODUCTION",
17867 "CONFIGURE_COMMAND",
17868 "INSTALLDIR",
17869 "BINDIR",
17870 "CONFIG_FILE_PATH",
17871 "DATADIR",
17872 "EXTENSION_DIR",
17873 "INCLUDE_PATH",
17874 "LIBDIR",
17875 "LOCALSTATEDIR",
17876 "SBINDIR",
17877 "SYSCONFDIR",
17878 "RELEASE",
17879 "SOURCE_ID",
17880 "SUBMINOR",
17881 "MINOR",
17882 "MINNOR",
17883 "MINORVERSION",
17884 "MAJOR",
17885 "MAJORVERSION",
17886 "MICRO",
17887 "MICROVERSION",
17888 "BINARY_AGE",
17889 "INTERFACE_AGE",
17890 "CORE_ABI",
17891 "PATCH",
17892 "COPYRIGHT",
17893 "TIMESTAMP",
17894 "REVISION",
17895 "PACKAGE_TAG",
17896 "PACKAGEDATE",
17897 "NUMVERSION",
17898 "Release",
17899 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017900);
17901
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017902sub constantFilter($$$)
17903{
17904 my ($Name, $Value, $Level) = @_;
17905
17906 if($Level eq "Binary")
17907 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017908 if($Name=~/_t\Z/)
17909 { # __malloc_ptr_t
17910 return 1;
17911 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017912 foreach (keys(%IgnoreConstant))
17913 {
17914 if($Name=~/(\A|_)$_(_|\Z)/)
17915 { # version
17916 return 1;
17917 }
17918 if(/\A[A-Z].*[a-z]\Z/)
17919 {
17920 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17921 { # version
17922 return 1;
17923 }
17924 }
17925 }
17926 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17927 { # version
17928 return 1;
17929 }
17930 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17931 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17932 return 1;
17933 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017934
17935 if($Value=~/\A["'].*['"]/i)
17936 { # string
17937 return 0;
17938 }
17939
17940 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17941 { # static int gcry_pth_init
17942 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017943 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017944 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017945 return 1;
17946 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017947 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017948 { # foo(p)
17949 return 1;
17950 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017951 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017952 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017953 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017954 return 1;
17955 }
17956 }
17957
17958 return 0;
17959}
17960
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017961sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017962{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017963 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017964 foreach my $Constant (keys(%{$Constants{1}}))
17965 {
17966 if($SkipConstants{1}{$Constant})
17967 { # skipped by the user
17968 next;
17969 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017970
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017971 if(my $Header = $Constants{1}{$Constant}{"Header"})
17972 {
17973 if(not is_target_header($Header, 1)
17974 and not is_target_header($Header, 2))
17975 { # user-defined header
17976 next;
17977 }
17978 }
17979 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017980 next;
17981 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017982
17983 my $Old_Value = uncoverConstant(1, $Constant);
17984
17985 if(constantFilter($Constant, $Old_Value, $Level))
17986 { # separate binary and source problems
17987 next;
17988 }
17989
17990 if(not defined $Constants{2}{$Constant}{"Value"})
17991 { # removed
17992 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17993 "Target"=>$Constant,
17994 "Old_Value"=>$Old_Value );
17995 next;
17996 }
17997
17998 if($Constants{2}{$Constant}{"Value"} eq "")
17999 { # empty value
18000 # TODO: implement a rule
18001 next;
18002 }
18003
18004 my $New_Value = uncoverConstant(2, $Constant);
18005
18006 my $Old_Value_Pure = $Old_Value;
18007 my $New_Value_Pure = $New_Value;
18008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018009 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18010 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18011 $New_Value_Pure=~s/(\W)\s+/$1/g;
18012 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018013
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018014 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018015
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018016 if($New_Value_Pure ne $Old_Value_Pure)
18017 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018018 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18019 { # complex values
18020 next;
18021 }
18022 if(computeValue($Old_Value) eq computeValue($New_Value))
18023 { # expressions
18024 next;
18025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018026 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18027 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18028 next;
18029 }
18030 if($Old_Value eq "0" and $New_Value eq "NULL")
18031 { # 0 => NULL
18032 next;
18033 }
18034 if($Old_Value eq "NULL" and $New_Value eq "0")
18035 { # NULL => 0
18036 next;
18037 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018038 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018039 "Target"=>$Constant,
18040 "Old_Value"=>$Old_Value,
18041 "New_Value"=>$New_Value );
18042 }
18043 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018044
18045 foreach my $Constant (keys(%{$Constants{2}}))
18046 {
18047 if(not defined $Constants{1}{$Constant}{"Value"})
18048 {
18049 if($SkipConstants{2}{$Constant})
18050 { # skipped by the user
18051 next;
18052 }
18053
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018054 if(my $Header = $Constants{2}{$Constant}{"Header"})
18055 {
18056 if(not is_target_header($Header, 1)
18057 and not is_target_header($Header, 2))
18058 { # user-defined header
18059 next;
18060 }
18061 }
18062 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018063 next;
18064 }
18065
18066 my $New_Value = uncoverConstant(2, $Constant);
18067 if(not defined $New_Value or $New_Value eq "") {
18068 next;
18069 }
18070
18071 if(constantFilter($Constant, $New_Value, $Level))
18072 { # separate binary and source problems
18073 next;
18074 }
18075
18076 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18077 "Target"=>$Constant,
18078 "New_Value"=>$New_Value );
18079 }
18080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018081}
18082
18083sub convert_integer($)
18084{
18085 my $Value = $_[0];
18086 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018087 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018088 return hex($Value);
18089 }
18090 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018091 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018092 return oct($Value);
18093 }
18094 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018095 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018096 return oct($Value);
18097 }
18098 else {
18099 return $Value;
18100 }
18101}
18102
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018103sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018104{
18105 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018106 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018107 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018108 {
18109 if($LibVersion==1)
18110 {
18111 printMsg("WARNING", "checking headers only");
18112 $CheckHeadersOnly = 1;
18113 }
18114 else {
18115 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18116 }
18117 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018118
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018119 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018120 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018121 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018122
18123 if($CheckUndefined)
18124 {
18125 my %UndefinedLibs = ();
18126
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018127 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18128
18129 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018130 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018131 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018132 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018133 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018134 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018135 if($Symbol_Library{$LibVersion}{$Symbol}
18136 or $DepSymbol_Library{$LibVersion}{$Symbol})
18137 { # exported by target library
18138 next;
18139 }
18140 if(index($Symbol, '@')!=-1)
18141 { # exported default symbol version (@@)
18142 $Symbol=~s/\@/\@\@/;
18143 if($Symbol_Library{$LibVersion}{$Symbol}
18144 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18145 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018146 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018148 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18149 $UndefinedLibs{$Path} = 1;
18150 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018151 }
18152 }
18153 }
18154 if($ExtraInfo)
18155 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018156 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018157 {
18158 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018159 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018160 foreach (@Paths)
18161 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018162 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018163 my ($Dir, $Name) = separate_path($_);
18164
18165 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018166 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018167 }
18168
18169 $Name = parse_libname($Name, "name", $OStarget);
18170 $Name=~s/\Alib//;
18171
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018172 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018173 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018174
18175 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18176 {
18177 $LibString = " -L".esc($Dir).$LibString;
18178 }
18179
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018180 writeFile($ExtraInfo."/libs-string", $LibString);
18181 }
18182 }
18183 }
18184
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018185 if($ExtraInfo) {
18186 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18187 }
18188
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018189 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018190 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018191 if($#LibPaths!=-1)
18192 {
18193 if(not keys(%{$Symbol_Library{$LibVersion}}))
18194 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018195 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018196 printMsg("WARNING", "checking headers only");
18197 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018198 }
18199 }
18200 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018201
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018202 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018203 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018204}
18205
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018206my %Prefix_Lib_Map=(
18207 # symbols for autodetecting library dependencies (by prefix)
18208 "pthread_" => ["libpthread"],
18209 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18210 "cairo_" => ["libcairo"],
18211 "gtk_" => ["libgtk-x11-2.0"],
18212 "atk_" => ["libatk-1.0"],
18213 "gdk_" => ["libgdk-x11-2.0"],
18214 "gl" => ["libGL"],
18215 "glu" => ["libGLU"],
18216 "popt" => ["libpopt"],
18217 "Py" => ["libpython"],
18218 "jpeg_" => ["libjpeg"],
18219 "BZ2_" => ["libbz2"],
18220 "Fc" => ["libfontconfig"],
18221 "Xft" => ["libXft"],
18222 "SSL_" => ["libssl"],
18223 "sem_" => ["libpthread"],
18224 "snd_" => ["libasound"],
18225 "art_" => ["libart_lgpl_2"],
18226 "dbus_g" => ["libdbus-glib-1"],
18227 "GOMP_" => ["libgomp"],
18228 "omp_" => ["libgomp"],
18229 "cms" => ["liblcms"]
18230);
18231
18232my %Pattern_Lib_Map=(
18233 "SL[a-z]" => ["libslang"]
18234);
18235
18236my %Symbol_Lib_Map=(
18237 # symbols for autodetecting library dependencies (by name)
18238 "pow" => "libm",
18239 "fmod" => "libm",
18240 "sin" => "libm",
18241 "floor" => "libm",
18242 "cos" => "libm",
18243 "dlopen" => "libdl",
18244 "deflate" => "libz",
18245 "inflate" => "libz",
18246 "move_panel" => "libpanel",
18247 "XOpenDisplay" => "libX11",
18248 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018249 "clock_gettime" => "librt",
18250 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018251);
18252
18253sub find_SymbolLibs($$)
18254{
18255 my ($LibVersion, $Symbol) = @_;
18256
18257 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18258 { # debug symbols
18259 return ();
18260 }
18261
18262 my %Paths = ();
18263
18264 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18265 {
18266 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18267 $Paths{$Path} = 1;
18268 }
18269 }
18270
18271 if(my $SymbolPrefix = getPrefix($Symbol))
18272 {
18273 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18274 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18275 }
18276
18277 if(not keys(%Paths))
18278 {
18279 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18280 {
18281 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18282 {
18283 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18284 $Paths{$Path} = 1;
18285 }
18286 }
18287 }
18288 }
18289
18290 if(not keys(%Paths))
18291 {
18292 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18293 {
18294 if($Symbol=~/\A$Prefix/)
18295 {
18296 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18297 {
18298 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18299 $Paths{$Path} = 1;
18300 }
18301 }
18302 }
18303 }
18304 }
18305
18306 if(not keys(%Paths))
18307 {
18308 if($SymbolPrefix)
18309 { # try to find a library by symbol prefix
18310 if($SymbolPrefix eq "inotify" and
18311 index($Symbol, "\@GLIBC")!=-1)
18312 {
18313 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18314 $Paths{$Path} = 1;
18315 }
18316 }
18317 else
18318 {
18319 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18320 $Paths{$Path} = 1;
18321 }
18322 }
18323 }
18324 }
18325
18326 if(my @Paths = keys(%Paths)) {
18327 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18328 }
18329 }
18330 return keys(%Paths);
18331}
18332
18333sub get_LibPath_Prefix($$)
18334{
18335 my ($LibVersion, $Prefix) = @_;
18336
18337 $Prefix = lc($Prefix);
18338 $Prefix=~s/[_]+\Z//g;
18339
18340 foreach ("-2", "2", "-1", "1", "")
18341 { # libgnome-2.so
18342 # libxml2.so
18343 # libdbus-1.so
18344 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18345 return $Path;
18346 }
18347 }
18348 return "";
18349}
18350
18351sub getPrefix($)
18352{
18353 my $Str = $_[0];
18354 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18355 { # XmuValidArea: Xmu
18356 return $1;
18357 }
18358 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18359 { # snfReadFont: snf
18360 return $1;
18361 }
18362 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18363 { # XRRTimes: XRR
18364 return $1;
18365 }
18366 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18367 { # H5HF_delete: H5
18368 return $1;
18369 }
18370 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18371 { # alarm_event_add: alarm_
18372 return $1;
18373 }
18374 elsif($Str=~/\A(([a-z])\2{1,})/i)
18375 { # ffopen
18376 return $1;
18377 }
18378 return "";
18379}
18380
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018381sub getSymbolSize($$)
18382{ # size from the shared library
18383 my ($Symbol, $LibVersion) = @_;
18384 return 0 if(not $Symbol);
18385 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18386 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18387 {
18388 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18389 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18390 {
18391 if($Size<0) {
18392 return -$Size;
18393 }
18394 }
18395 }
18396 return 0;
18397}
18398
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018399sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018400{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18401 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018402 my ($Name, $Type) = @_;
18403
18404 # single
18405 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018406 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018407 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018408 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018409 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018410
18411 # double
18412 if($Name=~/$DEFAULT_STD_PARMS/)
18413 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018414 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018415 {
18416 my ($ShortName, $FuncParams) = split_Signature($Name);
18417
18418 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18419 {
18420 if(index($FParam, "<")!=-1)
18421 {
18422 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18423 my $FParam_N = canonifyName($FParam, "T");
18424 if($FParam_N ne $FParam) {
18425 $Name=~s/\Q$FParam\E/$FParam_N/g;
18426 }
18427 }
18428 }
18429 }
18430 elsif($Type eq "T")
18431 {
18432 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18433
18434 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018435 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018436 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018437 my $FParam = $TParams[0];
18438 foreach my $Pos (1 .. $#TParams)
18439 {
18440 my $TParam = $TParams[$Pos];
18441 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18442 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18443 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018444 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018445 }
18446 }
18447 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018448 if($Type eq "S") {
18449 return formatName($Name, "S");
18450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018451 return $Name;
18452}
18453
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018454sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018455{
18456 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018457 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018458 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018459 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018460 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018461 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018462 next if($tr_name{$Symbol});
18463 $Symbol=~s/[\@\$]+(.*)\Z//;
18464 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018465 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018466 elsif(index($Symbol, "?")==0)
18467 {
18468 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018469 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018470 }
18471 else
18472 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018473 $tr_name{$Symbol} = $Symbol;
18474 $mangled_name_gcc{$Symbol} = $Symbol;
18475 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018476 }
18477 }
18478 if($#MnglNames1 > -1)
18479 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018480 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018481 foreach my $MnglName (@MnglNames1)
18482 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018483 if(my $Unmangled = pop(@UnmangledNames))
18484 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018485 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018486 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18487 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18488 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018489 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018490 and $tr_name{$MnglName}=~/vtable for (.+)/)
18491 { # bind class name and v-table symbol
18492 my $ClassName = $1;
18493 $ClassVTable{$ClassName} = $MnglName;
18494 $VTableClass{$MnglName} = $ClassName;
18495 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018496 }
18497 }
18498 }
18499 if($#MnglNames2 > -1)
18500 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018501 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018502 foreach my $MnglName (@MnglNames2)
18503 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018504 if(my $Unmangled = pop(@UnmangledNames))
18505 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018506 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018507 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018509 }
18510 }
18511 return \%tr_name;
18512}
18513
18514sub link_symbol($$$)
18515{
18516 my ($Symbol, $RunWith, $Deps) = @_;
18517 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18518 return 1;
18519 }
18520 if($Deps eq "+Deps")
18521 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018522 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018523 return 1;
18524 }
18525 }
18526 return 0;
18527}
18528
18529sub link_symbol_internal($$$)
18530{
18531 my ($Symbol, $RunWith, $Where) = @_;
18532 return 0 if(not $Where or not $Symbol);
18533 if($Where->{$RunWith}{$Symbol})
18534 { # the exact match by symbol name
18535 return 1;
18536 }
18537 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18538 { # indirect symbol version, i.e.
18539 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018540 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018541 if($Where->{$RunWith}{$VSym}) {
18542 return 1;
18543 }
18544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018545 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018546 if($Sym and $Ver)
18547 { # search for the symbol with the same version
18548 # or without version
18549 if($Where->{$RunWith}{$Sym})
18550 { # old: foo@v|foo@@v
18551 # new: foo
18552 return 1;
18553 }
18554 if($Where->{$RunWith}{$Sym."\@".$Ver})
18555 { # old: foo|foo@@v
18556 # new: foo@v
18557 return 1;
18558 }
18559 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18560 { # old: foo|foo@v
18561 # new: foo@@v
18562 return 1;
18563 }
18564 }
18565 return 0;
18566}
18567
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018568sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018569{
18570 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018571 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018572 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018573 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018574 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018575 my $NM = get_CmdPath("nm");
18576 if(not $NM) {
18577 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018578 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018579 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018580 while(<APP>)
18581 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018582 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018583 push(@Imported, $1);
18584 }
18585 }
18586 close(APP);
18587 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018588 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018589 {
18590 my $DumpBinCmd = get_CmdPath("dumpbin");
18591 if(not $DumpBinCmd) {
18592 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18593 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018594 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018595 while(<APP>)
18596 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018597 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18598 push(@Imported, $1);
18599 }
18600 }
18601 close(APP);
18602 }
18603 else
18604 {
18605 my $ReadelfCmd = get_CmdPath("readelf");
18606 if(not $ReadelfCmd) {
18607 exitStatus("Not_Found", "can't find \"readelf\"");
18608 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018609 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018610 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018611 while(<APP>)
18612 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018613 if(defined $symtab)
18614 { # do nothing with symtab
18615 if(index($_, "'.dynsym'")!=-1)
18616 { # dynamic table
18617 $symtab = undef;
18618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018619 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018620 elsif(index($_, "'.symtab'")!=-1)
18621 { # symbol table
18622 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018623 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018624 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018625 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018626 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18627 if($Ndx eq "UND")
18628 { # only imported symbols
18629 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018630 }
18631 }
18632 }
18633 close(APP);
18634 }
18635 return @Imported;
18636}
18637
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018638my %ELF_BIND = map {$_=>1} (
18639 "WEAK",
18640 "GLOBAL"
18641);
18642
18643my %ELF_TYPE = map {$_=>1} (
18644 "FUNC",
18645 "IFUNC",
18646 "OBJECT",
18647 "COMMON"
18648);
18649
18650my %ELF_VIS = map {$_=>1} (
18651 "DEFAULT",
18652 "PROTECTED"
18653);
18654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018655sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018656{ # read the line of 'readelf' output corresponding to the symbol
18657 my @Info = split(/\s+/, $_[0]);
18658 # Num: Value Size Type Bind Vis Ndx Name
18659 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018660 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018661 shift(@Info); # spaces
18662 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018663
18664 if($#Info==7)
18665 { # UND SYMBOL (N)
18666 if($Info[7]=~/\(\d+\)/) {
18667 pop(@Info);
18668 }
18669 }
18670
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018671 if($#Info!=6)
18672 { # other lines
18673 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018674 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018675 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018676 return () if(not defined $ELF_BIND{$Info[3]});
18677 return () if(not defined $ELF_VIS{$Info[4]});
18678 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18679 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18680 return ();
18681 }
18682 if($OStarget eq "symbian")
18683 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18684 if(index($Info[6], "_._.absent_export_")!=-1)
18685 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18686 return ();
18687 }
18688 $Info[6]=~s/\@.+//g; # remove version
18689 }
18690 if(index($Info[2], "0x") == 0)
18691 { # size == 0x3d158
18692 $Info[2] = hex($Info[2]);
18693 }
18694 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018695}
18696
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018697sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018698{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018699 my ($LibVersion, $Name) = @_;
18700 return "" if(not $LibVersion or not $Name);
18701 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18702 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018703 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018704 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18705}
18706
18707sub get_LibPath_I($$)
18708{
18709 my ($LibVersion, $Name) = @_;
18710 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018711 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018712 if(-f $Name)
18713 { # absolute path
18714 return $Name;
18715 }
18716 else
18717 { # broken
18718 return "";
18719 }
18720 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018721 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018722 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018723 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018724 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018725 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018726 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018727 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018728 }
18729 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18730 { # ldconfig default paths
18731 return $DefaultPath;
18732 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018733 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018734 { # search in default linker directories
18735 # and then in all system paths
18736 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018737 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018738 }
18739 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018740 if(not defined $Cache{"checkSystemFiles"}) {
18741 checkSystemFiles();
18742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018743 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18744 return $AllObjects[0];
18745 }
18746 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18747 {
18748 if($ShortName ne $Name)
18749 { # FIXME: check this case
18750 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18751 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018752 }
18753 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018754 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018755 # can't find
18756 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018757}
18758
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018759sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018760{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18762 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018763
18764 my $Real_Path = realpath($Lib_Path);
18765
18766 if(not $Real_Path)
18767 { # broken link
18768 return ();
18769 }
18770
18771 my $Lib_Name = get_filename($Real_Path);
18772
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018773 if($ExtraInfo)
18774 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018775 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018776 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018777 }
18778
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018779 if($IsNeededLib)
18780 {
18781 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18782 return ();
18783 }
18784 }
18785 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018786 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018788 push(@RecurLib, $Lib_Name);
18789 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018790 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18791
18792 if(not $IsNeededLib)
18793 { # special cases: libstdc++ and libc
18794 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18795 {
18796 if($ShortName eq "libstdc++")
18797 { # libstdc++.so.6
18798 $STDCXX_TESTING = 1;
18799 }
18800 elsif($ShortName eq "libc")
18801 { # libc-2.11.3.so
18802 $GLIBC_TESTING = 1;
18803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018804 }
18805 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018806 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018807 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018808 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018809 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018810 mkpath(get_dirname($DebugPath));
18811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018812 if($OStarget eq "macos")
18813 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018814 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018815 if(not $NM) {
18816 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018817 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018818 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018819 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018820 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018821 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018822 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018823 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018824 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018825 else
18826 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018827 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 while(<LIB>)
18830 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018831 if($CheckUndefined)
18832 {
18833 if(not $IsNeededLib)
18834 {
18835 if(/ U _([\w\$]+)\s*\Z/)
18836 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018837 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018838 next;
18839 }
18840 }
18841 }
18842
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018843 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018844 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018845 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018846 if($IsNeededLib)
18847 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018848 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018849 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018850 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18851 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018853 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018854 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018856 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18857 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018858 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18859 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018860 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018861 setLanguage($LibVersion, "C++");
18862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018864 }
18865 }
18866 }
18867 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018868
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018869 if($Deps)
18870 {
18871 if($LIB_TYPE eq "dynamic")
18872 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018873
18874 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018875 if(not $OtoolCmd) {
18876 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018877 }
18878
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018879 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18880 while(<LIB>)
18881 {
18882 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18883 and $1 ne $Lib_Path) {
18884 $NeededLib{$1} = 1;
18885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018887 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018889 }
18890 }
18891 elsif($OStarget eq "windows")
18892 { # Windows *.dll, *.lib
18893 my $DumpBinCmd = get_CmdPath("dumpbin");
18894 if(not $DumpBinCmd) {
18895 exitStatus("Not_Found", "can't find \"dumpbin\"");
18896 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018897 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018898 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018899 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018900 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018901 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018902 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018903 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018904 else
18905 { # write to pipe
18906 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018908 while(<LIB>)
18909 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18910 # 1198 4AD SetThreadToken (forwarded to ...)
18911 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018912 # 1 0 00005B30 ??0?N = ... (with pdb)
18913 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018914 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018915 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916 { # dynamic, static and forwarded symbols
18917 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018918 if($IsNeededLib)
18919 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018920 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018921 {
18922 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18923 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018925 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018926 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018927 {
18928 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18929 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018930 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18931 {
18932 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18933 setLanguage($LibVersion, "C++");
18934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018936 }
18937 }
18938 }
18939 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018940
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018941 if($Deps)
18942 {
18943 if($LIB_TYPE eq "dynamic")
18944 { # dependencies
18945 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18946 while(<LIB>)
18947 {
18948 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18949 and $1 ne $Lib_Path) {
18950 $NeededLib{path_format($1, $OSgroup)} = 1;
18951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018953 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018955 }
18956 }
18957 else
18958 { # Unix; *.so, *.a
18959 # Symbian: *.dso, *.lib
18960 my $ReadelfCmd = get_CmdPath("readelf");
18961 if(not $ReadelfCmd) {
18962 exitStatus("Not_Found", "can't find \"readelf\"");
18963 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018964 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018965 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018966 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018967 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018968 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018969 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018970 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018971 else
18972 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018973 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018974 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018975 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018976 while(<LIB>)
18977 {
18978 if($LIB_TYPE eq "dynamic")
18979 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018980 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018981 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018982 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018983 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018985 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018986 # do nothing with symtab
18987 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018988 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018989 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018991 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018992 next;
18993 }
18994 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018995 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018996 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018997 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018998 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018999 if($CheckUndefined)
19000 {
19001 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019002 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019003 }
19004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019005 next;
19006 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019007 if($Bind eq "WEAK")
19008 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019009 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019010 if($Weak eq "-Weak")
19011 { # skip WEAK symbols
19012 next;
19013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019014 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019015 my $Short = $Symbol;
19016 $Short=~s/\@.+//g;
19017 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019018 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019019 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19020 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019021 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019022 if($IsNeededLib)
19023 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019024 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019025 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019026 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19027 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019029 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019030 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019032 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19033 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19034 if($Vers)
19035 {
19036 if($LIB_EXT eq "so")
19037 { # value
19038 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19039 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019041 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019042 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19043 {
19044 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19045 setLanguage($LibVersion, "C++");
19046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019048 }
19049 }
19050 }
19051 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019052
19053 if($Deps and $LIB_TYPE eq "dynamic")
19054 { # dynamic library specifics
19055 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19056 open(LIB, $Cmd." |");
19057
19058 while(<LIB>)
19059 {
19060 if(/NEEDED.+\[([^\[\]]+)\]/)
19061 { # dependencies:
19062 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19063 $NeededLib{$1} = 1;
19064 }
19065 }
19066
19067 close(LIB);
19068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019069 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019070 if($Vers)
19071 {
19072 if(not $IsNeededLib and $LIB_EXT eq "so")
19073 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019074 my %Found = ();
19075
19076 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019077 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019078 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019079 next if(index($Symbol,"\@")==-1);
19080 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019081 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019082 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019083 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019084 if($Symbol_SameValue ne $Symbol
19085 and index($Symbol_SameValue,"\@")==-1)
19086 {
19087 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019088 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019089 last;
19090 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019091 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019092 }
19093 }
19094
19095 # default
19096 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19097 {
19098 next if(defined $Found{$Symbol});
19099 next if(index($Symbol,"\@\@")==-1);
19100
19101 if($Symbol=~/\A([^\@]*)\@\@/
19102 and not $SymVer{$LibVersion}{$1})
19103 {
19104 $SymVer{$LibVersion}{$1} = $Symbol;
19105 $Found{$Symbol} = 1;
19106 }
19107 }
19108
19109 # non-default
19110 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19111 {
19112 next if(defined $Found{$Symbol});
19113 next if(index($Symbol,"\@")==-1);
19114
19115 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19116 and not $SymVer{$LibVersion}{$1})
19117 {
19118 $SymVer{$LibVersion}{$1} = $Symbol;
19119 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019120 }
19121 }
19122 }
19123 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019124 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019125 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019126 foreach my $DyLib (sort keys(%NeededLib))
19127 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019128 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19129
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019130 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19131 {
19132 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19133 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19134 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019136 }
19137 }
19138 pop(@RecurLib);
19139 return $Library_Symbol{$LibVersion};
19140}
19141
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019142sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019143{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019145 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 return keys(%Prefixes);
19147}
19148
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019149sub get_prefixes_I($$)
19150{
19151 foreach my $P (@{$_[0]})
19152 {
19153 my @Parts = reverse(split(/[\/\\]+/, $P));
19154 my $Name = $Parts[0];
19155 foreach (1 .. $#Parts)
19156 {
19157 $_[1]->{$Name}{$P} = 1;
19158 last if($_>4 or $Parts[$_] eq "include");
19159 $Name = $Parts[$_].$SLASH.$Name;
19160 }
19161 }
19162}
19163
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019164sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019166 $Cache{"checkSystemFiles"} = 1;
19167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019169
19170 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 {
19172 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019173
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019174 my @Files = cmd_find($DevelPath,"f");
19175 foreach my $Link (cmd_find($DevelPath,"l"))
19176 { # add symbolic links
19177 if(-f $Link) {
19178 push(@Files, $Link);
19179 }
19180 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019181
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019182 # search for headers in /usr/lib
19183 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19184 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19185 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019186
19187 # search for libraries in /usr/lib (including symbolic links)
19188 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19189 foreach my $Path (@Libs)
19190 {
19191 my $N = get_filename($Path);
19192 $SystemObjects{$N}{$Path} = 1;
19193 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019194 }
19195 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019196
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019197 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019198 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019199 next if(not -d $DevelPath);
19200 # search for all header files in the /usr/include
19201 # with or without extension (ncurses.h, QtCore, ...)
19202 push(@SysHeaders, cmd_find($DevelPath,"f"));
19203 foreach my $Link (cmd_find($DevelPath,"l"))
19204 { # add symbolic links
19205 if(-f $Link) {
19206 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019208 }
19209 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019210 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211}
19212
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019213sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214{
19215 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019216 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019217 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19218 {
19219 if(not -e $Dest) {
19220 exitStatus("Access_Error", "can't access \'$Dest\'");
19221 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019222 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019223 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19224 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019225 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019226 }
19227 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019228 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019229}
19230
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019231sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232{
19233 my ($Path, $LibVersion) = @_;
19234 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019235 my $Name = get_filename($Path);
19236 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019237 return 1;
19238 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019239 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019240 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19241 return 1;
19242 }
19243 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19244 {
19245 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19246 return 1;
19247 }
19248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019249 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019251 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019252 return 1;
19253 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019254 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019255 return 1;
19256 }
19257 }
19258 return 0;
19259}
19260
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019261sub specificHeader($$)
19262{
19263 my ($Header, $Spec) = @_;
19264 my $Name = get_filename($Header);
19265
19266 if($Spec eq "windows")
19267 {# MS Windows
19268 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19269 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19270 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19271 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19272 my @Dirs = (
19273 "win32",
19274 "win64",
19275 "win",
19276 "windows",
19277 "msvcrt"
19278 ); # /gsf-win32/
19279 if(my $DIRs = join("|", @Dirs)) {
19280 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19281 }
19282 }
19283 elsif($Spec eq "macos")
19284 { # Mac OS
19285 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19286 }
19287
19288 return 0;
19289}
19290
19291sub skipAlienHeader($)
19292{
19293 my $Path = $_[0];
19294 my $Name = get_filename($Path);
19295 my $Dir = get_dirname($Path);
19296
19297 if($Tolerance=~/2/)
19298 { # 2 - skip internal headers
19299 my @Terms = (
19300 "p",
19301 "priv",
19302 "int",
19303 "impl",
19304 "implementation",
19305 "internal",
19306 "private",
19307 "old",
19308 "compat",
19309 "debug",
19310 "test",
19311 "gen"
19312 );
19313
19314 my @Dirs = (
19315 "private",
19316 "priv",
19317 "port",
19318 "impl",
19319 "internal",
19320 "detail",
19321 "details",
19322 "old",
19323 "compat",
19324 "debug",
19325 "config",
19326 "compiler",
19327 "platform",
19328 "test"
19329 );
19330
19331 if(my $TERMs = join("|", @Terms)) {
19332 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19333 }
19334 if(my $DIRs = join("|", @Dirs)) {
19335 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19336 }
19337
19338 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19339 }
19340
19341 if($Tolerance=~/1/)
19342 { # 1 - skip non-Linux headers
19343 if($OSgroup ne "windows")
19344 {
19345 if(specificHeader($Path, "windows")) {
19346 return 1;
19347 }
19348 }
19349 if($OSgroup ne "macos")
19350 {
19351 if(specificHeader($Path, "macos")) {
19352 return 1;
19353 }
19354 }
19355 }
19356
19357 # valid
19358 return 0;
19359}
19360
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019361sub skipHeader($$)
19362{
19363 my ($Path, $LibVersion) = @_;
19364 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019365 if(defined $Cache{"skipHeader"}{$Path}) {
19366 return $Cache{"skipHeader"}{$Path};
19367 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019368 if(defined $Tolerance and $Tolerance=~/1|2/)
19369 { # --tolerant
19370 if(skipAlienHeader($Path)) {
19371 return ($Cache{"skipHeader"}{$Path} = 1);
19372 }
19373 }
19374 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19375 return 0;
19376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019377 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19378}
19379
19380sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019381{ # returns:
19382 # 1 - if header should NOT be included and checked
19383 # 2 - if header should NOT be included, but should be checked
19384 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019385 my $Name = get_filename($Path);
19386 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019387 return $Kind;
19388 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019389 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19390 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019391 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019392 if(index($Path, $D)!=-1)
19393 {
19394 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19395 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019397 }
19398 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019399 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19400 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019402 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19403 {
19404 if($Name=~/$P/) {
19405 return $Kind;
19406 }
19407 if($P=~/[\/\\]/ and $Path=~/$P/) {
19408 return $Kind;
19409 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019410 }
19411 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019413 return 0;
19414}
19415
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019416sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417{
19418 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019419 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019420 { # system directory
19421 return;
19422 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019423 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019424 { # already registered
19425 return;
19426 }
19427 foreach my $Path (find_libs($Dir,"",1))
19428 {
19429 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019430 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019431 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19434}
19435
19436sub registerObject($$)
19437{
19438 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019439
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019440 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019441 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019442 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019443 {
19444 if(my $SONAME = getSONAME($Path)) {
19445 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19446 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019447 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019448 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19449 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019450 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019451
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019452 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019453 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019454 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019455 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019456 if($ObjArch ne getArch_GCC($LibVersion))
19457 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19458 $CheckedArch{$LibVersion} = 1;
19459 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 +040019460 }
19461 }
19462 }
19463}
19464
19465sub getArch_Object($)
19466{
19467 my $Path = $_[0];
19468
19469 my %MachineType = (
19470 "14C" => "x86",
19471 "8664" => "x86_64",
19472 "1C0" => "arm",
19473 "200" => "ia64"
19474 );
19475
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019476 my %ArchName = (
19477 "s390:31-bit" => "s390",
19478 "s390:64-bit" => "s390x",
19479 "powerpc:common" => "ppc32",
19480 "powerpc:common64" => "ppc64",
19481 "i386:x86-64" => "x86_64",
19482 "mips:3000" => "mips",
19483 "sparc:v8plus" => "sparcv9"
19484 );
19485
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019486 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019487 {
19488 my $DumpbinCmd = get_CmdPath("dumpbin");
19489 if(not $DumpbinCmd) {
19490 exitStatus("Not_Found", "can't find \"dumpbin\"");
19491 }
19492
19493 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19494 my $Out = `$Cmd`;
19495
19496 if($Out=~/(\w+)\smachine/)
19497 {
19498 if(my $Type = $MachineType{uc($1)})
19499 {
19500 return $Type;
19501 }
19502 }
19503 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019504 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019505 {
19506 my $ObjdumpCmd = get_CmdPath("objdump");
19507 if(not $ObjdumpCmd) {
19508 exitStatus("Not_Found", "can't find \"objdump\"");
19509 }
19510
19511 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019512
19513 if($OSgroup eq "windows") {
19514 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19515 }
19516 else {
19517 $Cmd = "LANG=$LOCALE ".$Cmd;
19518 }
19519 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019520
19521 if($Out=~/architecture:\s+([\w\-\:]+)/)
19522 {
19523 my $Arch = $1;
19524 if($Arch=~s/\:(.+)//)
19525 {
19526 my $Suffix = $1;
19527
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019528 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019529 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019530 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019531 }
19532 }
19533
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019534 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019535 $Arch = "x86";
19536 }
19537
19538 if($Arch eq "x86-64") {
19539 $Arch = "x86_64";
19540 }
19541
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019542 if($Arch eq "ia64-elf64") {
19543 $Arch = "ia64";
19544 }
19545
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019546 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019547 }
19548 }
19549 else
19550 { # macos, etc.
19551 # TODO
19552 }
19553
19554 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019555}
19556
19557sub getSONAME($)
19558{
19559 my $Path = $_[0];
19560 return if(not $Path);
19561 if(defined $Cache{"getSONAME"}{$Path}) {
19562 return $Cache{"getSONAME"}{$Path};
19563 }
19564 my $ObjdumpCmd = get_CmdPath("objdump");
19565 if(not $ObjdumpCmd) {
19566 exitStatus("Not_Found", "can't find \"objdump\"");
19567 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019568 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019569 if($OSgroup eq "windows") {
19570 $SonameCmd .= " | find \"SONAME\"";
19571 }
19572 else {
19573 $SonameCmd .= " | grep SONAME";
19574 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019575 if(my $SonameInfo = `$SonameCmd`)
19576 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019577 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19578 return ($Cache{"getSONAME"}{$Path} = $1);
19579 }
19580 }
19581 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019582}
19583
19584sub getSOPaths_Dest($$)
19585{
19586 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019587 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019588 return ();
19589 }
19590 if(-f $Dest)
19591 {
19592 if(not parse_libname($Dest, "name", $OStarget)) {
19593 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19594 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019595 registerObject($Dest, $LibVersion);
19596 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019597 return ($Dest);
19598 }
19599 elsif(-d $Dest)
19600 {
19601 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019602 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019603 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019604 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19605 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019606 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019607 { # all files and symlinks that match the name of a library
19608 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19609 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019610 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019611 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019612 }
19613 }
19614 }
19615 else
19616 { # search for all files and symlinks
19617 foreach my $Path (find_libs($Dest,"",""))
19618 {
19619 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019620 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019621 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019622 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019623 }
19624 if($OSgroup eq "macos")
19625 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019626 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019627 {
19628 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019629 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019630 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019631 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19632 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019633 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019634 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019635 }
19636 }
19637 }
19638 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019639 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640 }
19641 else {
19642 return ();
19643 }
19644}
19645
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019646sub isCyclical($$)
19647{
19648 my ($Stack, $Value) = @_;
19649 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019650}
19651
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019652sub getGCC_Opts($)
19653{ # to use in module
19654 my $LibVersion = $_[0];
19655
19656 my @Opts = ();
19657
19658 if($CompilerOptions{$LibVersion})
19659 { # user-defined options
19660 push(@Opts, $CompilerOptions{$LibVersion});
19661 }
19662 if($GccOptions)
19663 { # additional
19664 push(@Opts, $GccOptions);
19665 }
19666
19667 if(@Opts) {
19668 return join(" ", @Opts);
19669 }
19670
19671 return undef;
19672}
19673
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019674sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019675{
19676 my $LibVersion = $_[0];
19677
19678 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19679 return $Cache{"getArch_GCC"}{$LibVersion};
19680 }
19681
19682 my $Arch = undef;
19683
19684 if($GCC_PATH)
19685 {
19686 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19687
19688 my $Cmd = $GCC_PATH." test.c -o test";
19689 if(my $Opts = getGCC_Opts($LibVersion))
19690 { # user-defined options
19691 $Cmd .= " ".$Opts;
19692 }
19693
19694 chdir($TMP_DIR);
19695 system($Cmd);
19696 chdir($ORIG_DIR);
19697
19698 $Arch = getArch_Object("$TMP_DIR/test");
19699
19700 unlink("$TMP_DIR/test.c");
19701 unlink("$TMP_DIR/test");
19702 }
19703
19704 if(not $Arch) {
19705 exitStatus("Error", "can't check ARCH type");
19706 }
19707
19708 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19709}
19710
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019711sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019712{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019713 my $LibVersion = $_[0];
19714
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019715 my $Size = undef;
19716
19717 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019718 if(my $Arch = getArch($LibVersion))
19719 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019720 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019721 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019722 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019723 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19724 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019725 }
19726 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019727
19728 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019729 {
19730 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019731
19732 my $Cmd = $GCC_PATH." -E -dD empty.h";
19733 if(my $Opts = getGCC_Opts($LibVersion))
19734 { # user-defined options
19735 $Cmd .= " ".$Opts;
19736 }
19737
19738 chdir($TMP_DIR);
19739 my $Defines = `$Cmd`;
19740 chdir($ORIG_DIR);
19741
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019742 unlink("$TMP_DIR/empty.h");
19743
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019744 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19745 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019746 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019747 }
19748 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19749 { # GCC 3
19750 my $PTRDIFF = $1;
19751 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019752 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019753 }
19754 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019755 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019756 }
19757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019758 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019759
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019760 if(not $Size) {
19761 exitStatus("Error", "can't check WORD size");
19762 }
19763
19764 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019765}
19766
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019767sub getWordSize($)
19768{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019769 return $WORD_SIZE{$_[0]};
19770}
19771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019772sub majorVersion($)
19773{
19774 my $V = $_[0];
19775 return 0 if(not $V);
19776 my @VParts = split(/\./, $V);
19777 return $VParts[0];
19778}
19779
19780sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019781{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782 my ($V1, $V2) = @_;
19783 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019784 my @V1Parts = split(/\./, $V1);
19785 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019786 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19787 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019788 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19789 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19790 }
19791 return -1 if($#V1Parts < $#V2Parts);
19792 return 1 if($#V1Parts > $#V2Parts);
19793 return 0;
19794}
19795
19796sub read_ABI_Dump($$)
19797{
19798 my ($LibVersion, $Path) = @_;
19799 return if(not $LibVersion or not -e $Path);
19800 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019801 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019802 { # input *.abi
19803 $FilePath = $Path;
19804 }
19805 else
19806 { # input *.abi.tar.gz
19807 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019808 if(not isDump_U($FilePath)) {
19809 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019811 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019812
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019813 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019814
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019815 my $Line = readLineNum($FilePath, 0);
19816 if($Line=~/xml/)
19817 { # XML format
19818 loadModule("XmlDump");
19819 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019820 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019821 else
19822 { # Perl Data::Dumper format (default)
19823 open(DUMP, $FilePath);
19824 local $/ = undef;
19825 my $Content = <DUMP>;
19826 close(DUMP);
19827
19828 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19829 { # remove temp file
19830 unlink($FilePath);
19831 }
19832 if($Content!~/};\s*\Z/) {
19833 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19834 }
19835 $ABI = eval($Content);
19836 if(not $ABI) {
19837 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019839 }
19840 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019841 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019842 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019843 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019844 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019845 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019846 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019847 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019848 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019849
19850 if($ABI->{"ABI_DUMP_VERSION"})
19851 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019852 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019853 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019854 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019855 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019856 }
19857 else
19858 { # support for old ABI dumps
19859 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019860 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019861 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019862 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019863 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019864
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019865 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019866 {
19867 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 +040019868 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019869
19870 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19871 { # DWARF ABI Dump
19872 $UseConv_Real{$LibVersion}{"P"} = 1;
19873 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19874
19875 $UsedDump{$LibVersion}{"DWARF"} = 1;
19876
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030019877 if(not $TargetComponent_Opt)
19878 {
19879 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
19880 $TargetComponent = "module";
19881 }
19882 else {
19883 $TargetComponent = "object";
19884 }
19885 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019886 }
19887
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019888 if(not checkDump($LibVersion, "2.11"))
19889 { # old ABI dumps
19890 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019891 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019892 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019893 { # ABI dump created with --binary option
19894 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19895 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019896 else
19897 { # default
19898 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19899 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019900
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019901 if(defined $ABI->{"Mode"}
19902 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019903 { # --ext option
19904 $ExtendedCheck = 1;
19905 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019906 if($ABI->{"Extra"}) {
19907 $ExtraDump = 1;
19908 }
19909
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019910 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019911 {
19912 $UsedDump{$LibVersion}{"L"} = $Lang;
19913 setLanguage($LibVersion, $Lang);
19914 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019915 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019916 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019917 }
19918 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019919 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019920 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019921 if(not $TInfo)
19922 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019923 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019924 }
19925 my %Tid_TDid = ();
19926 foreach my $TDid (keys(%{$TInfo}))
19927 {
19928 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19929 {
19930 $MAX_ID = $Tid if($Tid>$MAX_ID);
19931 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019932 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019933 }
19934 }
19935 my %NewID = ();
19936 foreach my $Tid (keys(%Tid_TDid))
19937 {
19938 my @TDids = keys(%{$Tid_TDid{$Tid}});
19939 if($#TDids>=1)
19940 {
19941 foreach my $TDid (@TDids)
19942 {
19943 if($TDid) {
19944 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19945 }
19946 else
19947 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019948 my $ID = ++$MAX_ID;
19949
19950 $NewID{$TDid}{$Tid} = $ID;
19951 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19952 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019953 }
19954 }
19955 }
19956 else
19957 {
19958 my $TDid = $TDids[0];
19959 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19960 }
19961 }
19962 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19963 {
19964 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19965 if(defined $Info{"BaseType"})
19966 {
19967 my $Bid = $Info{"BaseType"}{"Tid"};
19968 my $BDid = $Info{"BaseType"}{"TDid"};
19969 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019970 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019971 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19972 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19973 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019974 }
19975 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019978 read_Machine_DumpInfo($ABI, $LibVersion);
19979 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019980 if(not $SymbolInfo{$LibVersion})
19981 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019982 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019983 }
19984 if(not keys(%{$SymbolInfo{$LibVersion}}))
19985 { # validation of old-version dumps
19986 if(not $ExtendedCheck) {
19987 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19988 }
19989 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019990 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019991 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019992 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019993 else
19994 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019995 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019996 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019997 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019998 }
19999 if(not $DepSymbols)
20000 { # Cannot reconstruct DepSymbols. This may result in false
20001 # positives if the old dump is for library 2. Not a problem if
20002 # old dumps are only from old libraries.
20003 $DepSymbols = {};
20004 }
20005 foreach my $Symbol (keys(%{$DepSymbols})) {
20006 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020008 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020009 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020010
20011 if(my $V = $TargetVersion{$LibVersion}) {
20012 $Descriptor{$LibVersion}{"Version"} = $V;
20013 }
20014 else {
20015 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20016 }
20017
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020018 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 if(not $SkipTypes{$LibVersion})
20020 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020021 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020022 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020024 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020025 { # if not defined by -skip-symbols option
20026 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20027 if(not $SkipSymbols{$LibVersion})
20028 { # support for old dumps
20029 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20030 }
20031 if(not $SkipSymbols{$LibVersion})
20032 { # support for old dumps
20033 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020035 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020036 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020037
20038 if(not $TargetHeaders{$LibVersion})
20039 { # if not defined by -headers-list option
20040 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20041 }
20042
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020043 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020044 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020045 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020046 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020047 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020048 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020049
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020050 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020051 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020052
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020053 if(not checkDump($LibVersion, "2.10.1")
20054 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020055 { # support for old ABI dumps: added target headers
20056 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020057 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020058 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020059
20060 if(not $ABI->{"PublicABI"})
20061 {
20062 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20063 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20064 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020066 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020067 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020068 if(defined $ABI->{"GccConstants"})
20069 { # 3.0
20070 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20071 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20072 }
20073 }
20074
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020075 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020076 if(not $NestedNameSpaces{$LibVersion})
20077 { # support for old dumps
20078 # Cannot reconstruct NameSpaces. This may affect design
20079 # of the compatibility report.
20080 $NestedNameSpaces{$LibVersion} = {};
20081 }
20082 # target system type
20083 # needed to adopt HTML report
20084 if(not $DumpSystem)
20085 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020086 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020087 }
20088 # recreate environment
20089 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20090 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020091 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020092 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020093 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20094 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020095 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020096 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020097 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020098 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20099 {
20100 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20101 setLanguage($LibVersion, "C++");
20102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020103 }
20104 }
20105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020106 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20107 {
20108 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20109 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20110 }
20111 }
20112
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020114 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020115 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020116 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020117 {
20118 if(not $Symbol_Library{$LibVersion}{$MnglName}
20119 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20120 push(@VFunc, $MnglName);
20121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020122 }
20123 }
20124 translateSymbols(@VFunc, $LibVersion);
20125 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020126 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20127
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020128 if(not checkDump($LibVersion, "3.0"))
20129 { # support for old ABI dumps
20130 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20131 {
20132 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20133 {
20134 if(ref($BaseType) eq "HASH") {
20135 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20136 }
20137 }
20138 }
20139 }
20140
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020141 if(not checkDump($LibVersion, "3.2"))
20142 { # support for old ABI dumps
20143 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20144 {
20145 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20146 {
20147 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20148 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20149 }
20150 }
20151 }
20152
20153 # repair target headers list
20154 delete($TargetHeaders{$LibVersion});
20155 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020156 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20157 }
20158 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20159 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020160 }
20161
20162 # non-target constants from anon enums
20163 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20164 {
20165 if(not $ExtraDump
20166 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20167 {
20168 delete($Constants{$LibVersion}{$Name});
20169 }
20170 }
20171 }
20172
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020173 if(not checkDump($LibVersion, "2.20"))
20174 { # support for old ABI dumps
20175 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20176 {
20177 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20178
20179 if($TType=~/Struct|Union|Enum|Typedef/)
20180 { # repair complex types first
20181 next;
20182 }
20183
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020184 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020185 {
20186 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20187 if($BType=~/Struct|Union|Enum/i)
20188 {
20189 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20190 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20191 }
20192 }
20193 }
20194 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20195 {
20196 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20197 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20198 if($TType=~/Struct|Union|Enum/) {
20199 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20200 }
20201 }
20202 }
20203
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020204 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020205 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020206 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20207 { # support for old ABI dumps < 2.0 (ACC 1.22)
20208 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20209 {
20210 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20211 {
20212 if($Access ne "public") {
20213 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20214 }
20215 }
20216 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20217 }
20218 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20219 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020220 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20221 { # support for old ABI dumps
20222 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20223 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020224 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20225 { # DWARF ABI Dumps
20226 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20227 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020228 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20229 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020231 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20232 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020233 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020234 foreach (keys(%{$TInfo{"Base"}})) {
20235 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020236 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020237 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020238 if($TInfo{"Type"} eq "MethodPtr")
20239 {
20240 if(defined $TInfo{"Param"})
20241 { # support for old ABI dumps <= 1.17
20242 if(not defined $TInfo{"Param"}{"0"})
20243 {
20244 my $Max = keys(%{$TInfo{"Param"}});
20245 foreach my $Pos (1 .. $Max) {
20246 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20247 }
20248 delete($TInfo{"Param"}{$Max});
20249 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20250 }
20251 }
20252 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020253 if($TInfo{"BaseType"} eq $TypeId)
20254 { # fix ABI dump
20255 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20256 }
20257 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020258 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020259 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020260 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020261 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20262 if(not $BName)
20263 { # broken type
20264 next;
20265 }
20266 if($TInfo{"Name"} eq $BName)
20267 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020268 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020269 next;
20270 }
20271 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20272 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020273 }
20274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020275 }
20276 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20277 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020278 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020279 }
20280 }
20281
20282 if(not checkDump($LibVersion, "2.15"))
20283 { # support for old ABI dumps
20284 my %Dups = ();
20285 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20286 {
20287 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020288 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020289 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20290 { # remove template decls
20291 delete($SymbolInfo{$LibVersion}{$InfoId});
20292 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020294 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020295 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20296 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020297 { # templates
20298 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020299 }
20300 }
20301 }
20302
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020303 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20304 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020305 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20306 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20307 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20308 { # support for old ABI dumps (< 3.1)
20309 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20310 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20311 { # add "this" first parameter
20312 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20313 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20314
20315 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20316 {
20317 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20318 foreach my $Pos (reverse(0 .. $#Pos)) {
20319 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20320 }
20321 }
20322 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20323 }
20324 }
20325
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020326 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20327 { # ABI dumps have no mangled names for C-functions
20328 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20329 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020330 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20331 { # support for old ABI dumps
20332 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20333 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020334 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20335 { # DWARF ABI Dumps
20336 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20337 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020338 }
20339
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020340 $Descriptor{$LibVersion}{"Dump"} = 1;
20341}
20342
20343sub read_Machine_DumpInfo($$)
20344{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020345 my ($ABI, $LibVersion) = @_;
20346 if($ABI->{"Arch"}) {
20347 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020348 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020349 if($ABI->{"WordSize"}) {
20350 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020351 }
20352 else
20353 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020354 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020355 }
20356 if(not $WORD_SIZE{$LibVersion})
20357 { # support for old dumps (<1.23)
20358 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20359 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020360 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020361 }
20362 else
20363 {
20364 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020365 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020366 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020367 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20368 { # any "pointer"-type
20369 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020370 last;
20371 }
20372 }
20373 if($PSize)
20374 { # a pointer type size
20375 $WORD_SIZE{$LibVersion} = $PSize;
20376 }
20377 else {
20378 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20379 }
20380 }
20381 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020382 if($ABI->{"GccVersion"}) {
20383 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020384 }
20385}
20386
20387sub read_Libs_DumpInfo($$)
20388{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020389 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020390 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20391 if(not $Library_Symbol{$LibVersion})
20392 { # support for old dumps
20393 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20394 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020395 if(keys(%{$Library_Symbol{$LibVersion}})
20396 and not $DumpAPI) {
20397 $Descriptor{$LibVersion}{"Libs"} = "OK";
20398 }
20399}
20400
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020401sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020402{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020403 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020404
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020405 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020406 and not $DumpAPI) {
20407 $Descriptor{$LibVersion}{"Headers"} = "OK";
20408 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020409 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020410 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020411 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020412 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020413 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020414
20415 if(keys(%{$ABI->{"Sources"}})
20416 and not $DumpAPI) {
20417 $Descriptor{$LibVersion}{"Sources"} = "OK";
20418 }
20419 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020420 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020421 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20422 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020424}
20425
20426sub find_libs($$$)
20427{
20428 my ($Path, $Type, $MaxDepth) = @_;
20429 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020430 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020431}
20432
20433sub createDescriptor($$)
20434{
20435 my ($LibVersion, $Path) = @_;
20436 if(not $LibVersion or not $Path
20437 or not -e $Path) {
20438 return "";
20439 }
20440 if(-d $Path)
20441 { # directory with headers files and shared objects
20442 return "
20443 <version>
20444 ".$TargetVersion{$LibVersion}."
20445 </version>
20446
20447 <headers>
20448 $Path
20449 </headers>
20450
20451 <libs>
20452 $Path
20453 </libs>";
20454 }
20455 else
20456 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020457 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020458 { # standard XML-descriptor
20459 return readFile($Path);
20460 }
20461 elsif(is_header($Path, 2, $LibVersion))
20462 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020463 $CheckHeadersOnly = 1;
20464
20465 if($LibVersion==1) {
20466 $TargetVersion{$LibVersion} = "X";
20467 }
20468
20469 if($LibVersion==2) {
20470 $TargetVersion{$LibVersion} = "Y";
20471 }
20472
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020473 return "
20474 <version>
20475 ".$TargetVersion{$LibVersion}."
20476 </version>
20477
20478 <headers>
20479 $Path
20480 </headers>
20481
20482 <libs>
20483 none
20484 </libs>";
20485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020486 else
20487 { # standard XML-descriptor
20488 return readFile($Path);
20489 }
20490 }
20491}
20492
20493sub detect_lib_default_paths()
20494{
20495 my %LPaths = ();
20496 if($OSgroup eq "bsd")
20497 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020498 if(my $LdConfig = get_CmdPath("ldconfig"))
20499 {
20500 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20501 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020502 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20503 {
20504 my $Name = "lib".$1;
20505 if(not defined $LPaths{$Name}) {
20506 $LPaths{$Name} = $2;
20507 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 }
20509 }
20510 }
20511 else {
20512 printMsg("WARNING", "can't find ldconfig");
20513 }
20514 }
20515 else
20516 {
20517 if(my $LdConfig = get_CmdPath("ldconfig"))
20518 {
20519 if($SystemRoot and $OSgroup eq "linux")
20520 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20521 if(-e $SystemRoot."/etc/ld.so.conf") {
20522 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20523 }
20524 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020525 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20526 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020527 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20528 {
20529 my ($Name, $Path) = ($1, $2);
20530 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020531 if(not defined $LPaths{$Name})
20532 { # get first element from the list of available paths
20533
20534 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20535 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20536 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20537
20538 $LPaths{$Name} = $Path;
20539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020540 }
20541 }
20542 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020543 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020544 printMsg("WARNING", "can't find ldconfig");
20545 }
20546 }
20547 return \%LPaths;
20548}
20549
20550sub detect_bin_default_paths()
20551{
20552 my $EnvPaths = $ENV{"PATH"};
20553 if($OSgroup eq "beos") {
20554 $EnvPaths.=":".$ENV{"BETOOLS"};
20555 }
20556 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020557 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020558 {
20559 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020560 next if(not $Path);
20561 if($SystemRoot
20562 and $Path=~/\A\Q$SystemRoot\E\//)
20563 { # do NOT use binaries from target system
20564 next;
20565 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020566 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020567 }
20568}
20569
20570sub detect_inc_default_paths()
20571{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020572 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020573 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020574 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020575 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020576 next if(index($Line, "/cc1plus ")!=-1);
20577
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020578 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20579 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020580 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020581 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020582 if(index($Path, "c++")!=-1
20583 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020585 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 if(not defined $MAIN_CPP_DIR
20587 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20588 $MAIN_CPP_DIR = $Path;
20589 }
20590 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020591 elsif(index($Path, "gcc")!=-1) {
20592 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020593 }
20594 else
20595 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020596 if($Path=~/local[\/\\]+include/)
20597 { # local paths
20598 next;
20599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020600 if($SystemRoot
20601 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20602 { # The GCC include path for user headers is not a part of the system root
20603 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20604 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20605 next;
20606 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020607 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020608 }
20609 }
20610 }
20611 unlink("$TMP_DIR/empty.h");
20612 return %DPaths;
20613}
20614
20615sub detect_default_paths($)
20616{
20617 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20618 my $Search = $_[0];
20619 if($Search!~/inc/) {
20620 $HSearch = 0;
20621 }
20622 if($Search!~/lib/) {
20623 $LSearch = 0;
20624 }
20625 if($Search!~/bin/) {
20626 $BSearch = 0;
20627 }
20628 if($Search!~/gcc/) {
20629 $GSearch = 0;
20630 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020631 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020632 { # <search_headers> section of the XML descriptor
20633 # do NOT search for systems headers
20634 $HSearch = 0;
20635 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020636 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020637 { # <search_libs> section of the XML descriptor
20638 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020639 $LSearch = 0;
20640 }
20641 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20642 { # additional search paths
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);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020646 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020647 }
20648 if($OSgroup ne "windows")
20649 { # unix-like
20650 foreach my $Type ("include", "lib", "bin")
20651 { # automatic detection of system "devel" directories
20652 next if($Type eq "include" and not $HSearch);
20653 next if($Type eq "lib" and not $LSearch);
20654 next if($Type eq "bin" and not $BSearch);
20655 my ($UsrDir, $RootDir) = ("/usr", "/");
20656 if($SystemRoot and $Type ne "bin")
20657 { # 1. search for target headers and libraries
20658 # 2. use host commands: ldconfig, readelf, etc.
20659 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20660 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020661 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020662 if(-d $RootDir."/".$Type)
20663 { # if "/lib" is symbolic link
20664 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020665 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020666 }
20667 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020668 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020669 }
20670 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020671 if(-d $UsrDir)
20672 {
20673 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020674 if(-d $UsrDir."/".$Type)
20675 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020676 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020677 }
20678 }
20679 }
20680 }
20681 if($BSearch)
20682 {
20683 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020684 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020685 }
20686 # check environment variables
20687 if($OSgroup eq "beos")
20688 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020689 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020690 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020691 if($_ eq ".") {
20692 next;
20693 }
20694 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20695 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20696 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020697 }
20698 }
20699 if($HSearch)
20700 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020701 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20702 split(/:|;/, $ENV{"BEINCLUDES"})
20703 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 }
20705 if($LSearch)
20706 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020707 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20708 split(/:|;/, $ENV{"BELIBRARIES"}),
20709 split(/:|;/, $ENV{"LIBRARY_PATH"})
20710 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 }
20712 }
20713 if($LSearch)
20714 { # using linker to get system paths
20715 if(my $LPaths = detect_lib_default_paths())
20716 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020717 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020718 foreach my $Name (keys(%{$LPaths}))
20719 {
20720 if($SystemRoot
20721 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20722 { # wrong ldconfig configuration
20723 # check your <sysroot>/etc/ld.so.conf
20724 next;
20725 }
20726 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020727 if(my $Dir = get_dirname($LPaths->{$Name})) {
20728 $Dirs{$Dir} = 1;
20729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020730 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020731 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020733 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020734 }
20735 if($BSearch)
20736 {
20737 if($CrossGcc)
20738 { # --cross-gcc=arm-linux-gcc
20739 if(-e $CrossGcc)
20740 { # absolute or relative path
20741 $GCC_PATH = get_abs_path($CrossGcc);
20742 }
20743 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20744 { # command name
20745 $GCC_PATH = $CrossGcc;
20746 }
20747 else {
20748 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20749 }
20750 if($GCC_PATH=~/\s/) {
20751 $GCC_PATH = "\"".$GCC_PATH."\"";
20752 }
20753 }
20754 }
20755 if($GSearch)
20756 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020757 if(not $CrossGcc)
20758 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020759 $GCC_PATH = get_CmdPath("gcc");
20760 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020761 if(not $GCC_PATH)
20762 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020763 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020764 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020765 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020766 { # select the latest version
20767 @GCCs = sort {$b cmp $a} @GCCs;
20768 if(check_gcc($GCCs[0], "3"))
20769 {
20770 $GCC_PATH = $GCCs[0];
20771 last;
20772 }
20773 }
20774 }
20775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776 if(not $GCC_PATH) {
20777 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20778 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020779
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020780 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020781 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020782 my $GccTarget = get_dumpmachine($GCC_PATH);
20783
20784 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020786 $OStarget = "linux";
20787 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020788 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020789 elsif($GccTarget=~/symbian/)
20790 {
20791 $OStarget = "symbian";
20792 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20793 }
20794
20795 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20796
20797 # check GCC version
20798 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20799 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20800 # introduced in 4.8
20801 # fixed in 4.8.3
20802 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20803 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020804 }
20805 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020806 else {
20807 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020808 }
20809 }
20810 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020811 {
20812 # GCC standard paths
20813 if($GCC_PATH and not $NoStdInc)
20814 {
20815 my %DPaths = detect_inc_default_paths();
20816 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20817 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20818 @DefaultIncPaths = @{$DPaths{"Inc"}};
20819 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20820 }
20821
20822 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020823 my $IncPath = "/usr/include";
20824 if($SystemRoot) {
20825 $IncPath = $SystemRoot.$IncPath;
20826 }
20827 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020828 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020829 }
20830 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020831
20832 if($ExtraInfo)
20833 {
20834 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20835 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020837}
20838
20839sub getLIB_EXT($)
20840{
20841 my $Target = $_[0];
20842 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20843 return $Ext;
20844 }
20845 return $OS_LibExt{$LIB_TYPE}{"default"};
20846}
20847
20848sub getAR_EXT($)
20849{
20850 my $Target = $_[0];
20851 if(my $Ext = $OS_Archive{$Target}) {
20852 return $Ext;
20853 }
20854 return $OS_Archive{"default"};
20855}
20856
20857sub get_dumpversion($)
20858{
20859 my $Cmd = $_[0];
20860 return "" if(not $Cmd);
20861 if($Cache{"get_dumpversion"}{$Cmd}) {
20862 return $Cache{"get_dumpversion"}{$Cmd};
20863 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020864 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020865 chomp($V);
20866 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20867}
20868
20869sub get_dumpmachine($)
20870{
20871 my $Cmd = $_[0];
20872 return "" if(not $Cmd);
20873 if($Cache{"get_dumpmachine"}{$Cmd}) {
20874 return $Cache{"get_dumpmachine"}{$Cmd};
20875 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020876 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020877 chomp($Machine);
20878 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20879}
20880
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020881sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020882{
20883 my $Cmd = $_[0];
20884 return "" if(not $Cmd);
20885 my @Options = (
20886 "--version",
20887 "-help"
20888 );
20889 foreach my $Opt (@Options)
20890 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020891 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020892 if($Info) {
20893 return 1;
20894 }
20895 }
20896 return 0;
20897}
20898
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020899sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020901 my ($Cmd, $ReqVer) = @_;
20902 return 0 if(not $Cmd or not $ReqVer);
20903 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20904 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020906 if(my $GccVer = get_dumpversion($Cmd))
20907 {
20908 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20909 if(cmpVersions($GccVer, $ReqVer)>=0) {
20910 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20911 }
20912 }
20913 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020914}
20915
20916sub get_depth($)
20917{
20918 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020919 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020920 }
20921 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20922}
20923
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020924sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020925{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020926 return if($Cache{"registerGccHeaders"}); # this function should be called once
20927
20928 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020929 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020930 my @Headers = cmd_find($Path,"f");
20931 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20932 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020933 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020934 my $FileName = get_filename($HPath);
20935 if(not defined $DefaultGccHeader{$FileName})
20936 { # skip duplicated
20937 $DefaultGccHeader{$FileName} = $HPath;
20938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020939 }
20940 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020941 $Cache{"registerGccHeaders"} = 1;
20942}
20943
20944sub registerCppHeaders()
20945{
20946 return if($Cache{"registerCppHeaders"}); # this function should be called once
20947
20948 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020950 my @Headers = cmd_find($CppDir,"f");
20951 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20952 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020954 my $FileName = get_filename($Path);
20955 if(not defined $DefaultCppHeader{$FileName})
20956 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020957 $DefaultCppHeader{$FileName} = $Path;
20958 }
20959 }
20960 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020961 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020962}
20963
20964sub parse_libname($$$)
20965{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020966 return "" if(not $_[0]);
20967 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20968 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020969 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020970 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20971}
20972
20973sub parse_libname_I($$$)
20974{
20975 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020976
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020977 if($Target eq "symbian") {
20978 return parse_libname_symbian($Name, $Type);
20979 }
20980 elsif($Target eq "windows") {
20981 return parse_libname_windows($Name, $Type);
20982 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020983
20984 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020985 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020986 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987 { # libSDL-1.2.so.0.7.1
20988 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020989 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020990 if($Type eq "name")
20991 { # libSDL-1.2
20992 # libwbxml2
20993 return $2;
20994 }
20995 elsif($Type eq "name+ext")
20996 { # libSDL-1.2.so
20997 # libwbxml2.so
20998 return $1;
20999 }
21000 elsif($Type eq "version")
21001 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021002 if(defined $7
21003 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021004 { # 0.7.1
21005 return $7;
21006 }
21007 else
21008 { # libc-2.5.so (=>2.5 version)
21009 my $MV = $5;
21010 $MV=~s/\A[\-\_]+//g;
21011 return $MV;
21012 }
21013 }
21014 elsif($Type eq "short")
21015 { # libSDL
21016 # libwbxml2
21017 return $3;
21018 }
21019 elsif($Type eq "shortest")
21020 { # SDL
21021 # wbxml
21022 return shortest_name($3);
21023 }
21024 }
21025 return "";# error
21026}
21027
21028sub parse_libname_symbian($$)
21029{
21030 my ($Name, $Type) = @_;
21031 my $Ext = getLIB_EXT("symbian");
21032 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21033 { # libpthread{00010001}.dso
21034 if($Type eq "name")
21035 { # libpthread{00010001}
21036 return $2;
21037 }
21038 elsif($Type eq "name+ext")
21039 { # libpthread{00010001}.dso
21040 return $1;
21041 }
21042 elsif($Type eq "version")
21043 { # 00010001
21044 my $V = $4;
21045 $V=~s/\{(.+)\}/$1/;
21046 return $V;
21047 }
21048 elsif($Type eq "short")
21049 { # libpthread
21050 return $3;
21051 }
21052 elsif($Type eq "shortest")
21053 { # pthread
21054 return shortest_name($3);
21055 }
21056 }
21057 return "";# error
21058}
21059
21060sub parse_libname_windows($$)
21061{
21062 my ($Name, $Type) = @_;
21063 my $Ext = getLIB_EXT("windows");
21064 if($Name=~/((.+?)\.$Ext)\Z/)
21065 { # netapi32.dll
21066 if($Type eq "name")
21067 { # netapi32
21068 return $2;
21069 }
21070 elsif($Type eq "name+ext")
21071 { # netapi32.dll
21072 return $1;
21073 }
21074 elsif($Type eq "version")
21075 { # DLL version embedded
21076 # at binary-level
21077 return "";
21078 }
21079 elsif($Type eq "short")
21080 { # netapi32
21081 return $2;
21082 }
21083 elsif($Type eq "shortest")
21084 { # netapi
21085 return shortest_name($2);
21086 }
21087 }
21088 return "";# error
21089}
21090
21091sub shortest_name($)
21092{
21093 my $Name = $_[0];
21094 # remove prefix
21095 $Name=~s/\A(lib|open)//;
21096 # remove suffix
21097 $Name=~s/[\W\d_]+\Z//i;
21098 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21099 return $Name;
21100}
21101
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021102sub createSymbolsList($$$$$)
21103{
21104 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021105
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021106 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021107 prepareSymbols(1);
21108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021109 my %SymbolHeaderLib = ();
21110 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021112 # Get List
21113 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21114 {
21115 if(not link_symbol($Symbol, 1, "-Deps"))
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 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021119 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021120 { # skip other symbols
21121 next;
21122 }
21123 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21124 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021125 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021126 next;
21127 }
21128 my $DyLib = $Symbol_Library{1}{$Symbol};
21129 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021130 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021131 next;
21132 }
21133 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21134 $Total+=1;
21135 }
21136 # Draw List
21137 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21138 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21139 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21140 {
21141 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21142 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 my %NS_Symbol = ();
21144 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021145 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021146 }
21147 foreach my $NameSpace (sort keys(%NS_Symbol))
21148 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021149 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021150 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21151 foreach my $Symbol (@SortedInterfaces)
21152 {
21153 my $SubReport = "";
21154 my $Signature = get_Signature($Symbol, 1);
21155 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021156 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 }
21158 if($Symbol=~/\A(_Z|\?)/)
21159 {
21160 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021161 $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 +040021162 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021163 else {
21164 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21165 }
21166 }
21167 else
21168 {
21169 if($Signature) {
21170 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21171 }
21172 else {
21173 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21174 }
21175 }
21176 $SYMBOLS_LIST .= $SubReport;
21177 }
21178 }
21179 $SYMBOLS_LIST .= "<br/>\n";
21180 }
21181 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021182 # clear info
21183 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21184 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21185 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21186 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021187 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021188 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021189 my $CssStyles = readModule("Styles", "SymbolsList.css");
21190 my $JScripts = readModule("Scripts", "Sections.js");
21191 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021192 my $Title = "$LName: public symbols";
21193 my $Keywords = "$LName, API, symbols";
21194 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021195 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021196 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021197 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021198 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021199 writeFile($SaveTo, $SYMBOLS_LIST);
21200}
21201
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021202sub add_target_libs($)
21203{
21204 foreach (@{$_[0]}) {
21205 $TargetLibs{$_} = 1;
21206 }
21207}
21208
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021209sub is_target_lib($)
21210{
21211 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021212 if(not $LName) {
21213 return 0;
21214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021215 if($TargetLibraryName
21216 and $LName!~/\Q$TargetLibraryName\E/) {
21217 return 0;
21218 }
21219 if(keys(%TargetLibs)
21220 and not $TargetLibs{$LName}
21221 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21222 return 0;
21223 }
21224 return 1;
21225}
21226
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021227sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021228{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021229 my ($H, $V) = @_;
21230 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021231 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021232 if($TargetHeaders{$V}{$H}) {
21233 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021234 }
21235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021236 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021237}
21238
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021239sub readLibs($)
21240{
21241 my $LibVersion = $_[0];
21242 if($OStarget eq "windows")
21243 { # dumpbin.exe will crash
21244 # without VS Environment
21245 check_win32_env();
21246 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021247 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021248 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021249 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021250}
21251
21252sub dump_sorting($)
21253{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021254 my $Hash = $_[0];
21255 return [] if(not $Hash);
21256 my @Keys = keys(%{$Hash});
21257 return [] if($#Keys<0);
21258 if($Keys[0]=~/\A\d+\Z/)
21259 { # numbers
21260 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021261 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021262 else
21263 { # strings
21264 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021265 }
21266}
21267
21268sub printMsg($$)
21269{
21270 my ($Type, $Msg) = @_;
21271 if($Type!~/\AINFO/) {
21272 $Msg = $Type.": ".$Msg;
21273 }
21274 if($Type!~/_C\Z/) {
21275 $Msg .= "\n";
21276 }
21277 if($Quiet)
21278 { # --quiet option
21279 appendFile($COMMON_LOG_PATH, $Msg);
21280 }
21281 else
21282 {
21283 if($Type eq "ERROR") {
21284 print STDERR $Msg;
21285 }
21286 else {
21287 print $Msg;
21288 }
21289 }
21290}
21291
21292sub exitStatus($$)
21293{
21294 my ($Code, $Msg) = @_;
21295 printMsg("ERROR", $Msg);
21296 exit($ERROR_CODE{$Code});
21297}
21298
21299sub exitReport()
21300{ # the tool has run without any errors
21301 printReport();
21302 if($COMPILE_ERRORS)
21303 { # errors in headers may add false positives/negatives
21304 exit($ERROR_CODE{"Compile_Error"});
21305 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021306 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21307 { # --binary
21308 exit($ERROR_CODE{"Incompatible"});
21309 }
21310 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21311 { # --source
21312 exit($ERROR_CODE{"Incompatible"});
21313 }
21314 elsif($RESULT{"Source"}{"Problems"}
21315 or $RESULT{"Binary"}{"Problems"})
21316 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021317 exit($ERROR_CODE{"Incompatible"});
21318 }
21319 else {
21320 exit($ERROR_CODE{"Compatible"});
21321 }
21322}
21323
21324sub readRules($)
21325{
21326 my $Kind = $_[0];
21327 if(not -f $RULES_PATH{$Kind}) {
21328 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21329 }
21330 my $Content = readFile($RULES_PATH{$Kind});
21331 while(my $Rule = parseTag(\$Content, "rule"))
21332 {
21333 my $RId = parseTag(\$Rule, "id");
21334 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21335 foreach my $Prop (@Properties) {
21336 if(my $Value = parseTag(\$Rule, lc($Prop)))
21337 {
21338 $Value=~s/\n[ ]*//;
21339 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21340 }
21341 }
21342 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21343 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21344 }
21345 else {
21346 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21347 }
21348 }
21349}
21350
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021351sub getReportPath($)
21352{
21353 my $Level = $_[0];
21354 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21355 if($Level eq "Binary")
21356 {
21357 if($BinaryReportPath)
21358 { # --bin-report-path
21359 return $BinaryReportPath;
21360 }
21361 elsif($OutputReportPath)
21362 { # --report-path
21363 return $OutputReportPath;
21364 }
21365 else
21366 { # default
21367 return $Dir."/abi_compat_report.$ReportFormat";
21368 }
21369 }
21370 elsif($Level eq "Source")
21371 {
21372 if($SourceReportPath)
21373 { # --src-report-path
21374 return $SourceReportPath;
21375 }
21376 elsif($OutputReportPath)
21377 { # --report-path
21378 return $OutputReportPath;
21379 }
21380 else
21381 { # default
21382 return $Dir."/src_compat_report.$ReportFormat";
21383 }
21384 }
21385 else
21386 {
21387 if($OutputReportPath)
21388 { # --report-path
21389 return $OutputReportPath;
21390 }
21391 else
21392 { # default
21393 return $Dir."/compat_report.$ReportFormat";
21394 }
21395 }
21396}
21397
21398sub printStatMsg($)
21399{
21400 my $Level = $_[0];
21401 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21402}
21403
21404sub listAffected($)
21405{
21406 my $Level = $_[0];
21407 my $List = "";
21408 foreach (keys(%{$TotalAffected{$Level}}))
21409 {
21410 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21411 { # skip "Low"-severity problems
21412 next;
21413 }
21414 $List .= "$_\n";
21415 }
21416 my $Dir = get_dirname(getReportPath($Level));
21417 if($Level eq "Binary") {
21418 writeFile($Dir."/abi_affected.txt", $List);
21419 }
21420 elsif($Level eq "Source") {
21421 writeFile($Dir."/src_affected.txt", $List);
21422 }
21423}
21424
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021425sub printReport()
21426{
21427 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021428 createReport();
21429 if($JoinReport or $DoubleReport)
21430 {
21431 if($RESULT{"Binary"}{"Problems"}
21432 or $RESULT{"Source"}{"Problems"}) {
21433 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021434 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021435 else {
21436 printMsg("INFO", "result: COMPATIBLE");
21437 }
21438 printStatMsg("Binary");
21439 printStatMsg("Source");
21440 if($ListAffected)
21441 { # --list-affected
21442 listAffected("Binary");
21443 listAffected("Source");
21444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021445 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021446 elsif($BinaryOnly)
21447 {
21448 if($RESULT{"Binary"}{"Problems"}) {
21449 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21450 }
21451 else {
21452 printMsg("INFO", "result: COMPATIBLE");
21453 }
21454 printStatMsg("Binary");
21455 if($ListAffected)
21456 { # --list-affected
21457 listAffected("Binary");
21458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021459 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021460 elsif($SourceOnly)
21461 {
21462 if($RESULT{"Source"}{"Problems"}) {
21463 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21464 }
21465 else {
21466 printMsg("INFO", "result: COMPATIBLE");
21467 }
21468 printStatMsg("Source");
21469 if($ListAffected)
21470 { # --list-affected
21471 listAffected("Source");
21472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021473 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021474 if($StdOut)
21475 {
21476 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021477 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021478 printMsg("INFO", "compatibility report has been generated to stdout");
21479 }
21480 else
21481 { # default
21482 printMsg("INFO", "compatibility reports have been generated to stdout");
21483 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021484 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021485 else
21486 {
21487 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021488 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021489 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21490 }
21491 elsif($DoubleReport)
21492 { # default
21493 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21494 }
21495 elsif($BinaryOnly)
21496 { # --binary
21497 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21498 }
21499 elsif($SourceOnly)
21500 { # --source
21501 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021503 }
21504}
21505
21506sub check_win32_env()
21507{
21508 if(not $ENV{"DevEnvDir"}
21509 or not $ENV{"LIB"}) {
21510 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21511 }
21512}
21513
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021514sub diffSets($$)
21515{
21516 my ($S1, $S2) = @_;
21517 my @SK1 = keys(%{$S1});
21518 my @SK2 = keys(%{$S2});
21519 if($#SK1!=$#SK2) {
21520 return 1;
21521 }
21522 foreach my $K1 (@SK1)
21523 {
21524 if(not defined $S2->{$K1}) {
21525 return 1;
21526 }
21527 }
21528 return 0;
21529}
21530
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021531sub defaultDumpPath($$)
21532{
21533 my ($N, $V) = @_;
21534 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21535}
21536
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021537sub create_ABI_Dump()
21538{
21539 if(not -e $DumpAPI) {
21540 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21541 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021542
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021543 if(isDump($DumpAPI)) {
21544 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021545 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021546 else {
21547 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021548 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021549
21550 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021551 { # set to default: N
21552 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021553 }
21554
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021555 initLogging(1);
21556 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021557
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021558 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021559 if($OutputDumpPath)
21560 { # user defined path
21561 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021562 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021563 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21564
21565 if(not $Archive and not $StdOut)
21566 { # check archive utilities
21567 if($OSgroup eq "windows")
21568 { # using zip
21569 my $ZipCmd = get_CmdPath("zip");
21570 if(not $ZipCmd) {
21571 exitStatus("Not_Found", "can't find \"zip\"");
21572 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021573 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021574 else
21575 { # using tar and gzip
21576 my $TarCmd = get_CmdPath("tar");
21577 if(not $TarCmd) {
21578 exitStatus("Not_Found", "can't find \"tar\"");
21579 }
21580 my $GzipCmd = get_CmdPath("gzip");
21581 if(not $GzipCmd) {
21582 exitStatus("Not_Found", "can't find \"gzip\"");
21583 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021584 }
21585 }
21586
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021587 if(not $Descriptor{1}{"Dump"})
21588 {
21589 if(not $CheckHeadersOnly) {
21590 readLibs(1);
21591 }
21592 if($CheckHeadersOnly) {
21593 setLanguage(1, "C++");
21594 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021595 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021596 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021597 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021598 if(not $Descriptor{1}{"Dump"})
21599 {
21600 if($Descriptor{1}{"Headers"}) {
21601 readHeaders(1);
21602 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021603 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021604 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021605 if(not keys(%{$SymbolInfo{1}}))
21606 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021607 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021608 {
21609 if($CheckHeadersOnly) {
21610 exitStatus("Empty_Set", "the set of public symbols is empty");
21611 }
21612 else {
21613 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21614 }
21615 }
21616 }
21617 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021618 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021619 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21620 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021621 if($ExtraDump)
21622 { # add unmangled names to the ABI dump
21623 my @Names = ();
21624 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21625 {
21626 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21627 push(@Names, $MnglName);
21628 }
21629 }
21630 translateSymbols(@Names, 1);
21631 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21632 {
21633 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21634 {
21635 if(my $Unmangled = $tr_name{$MnglName})
21636 {
21637 if($MnglName ne $Unmangled) {
21638 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21639 }
21640 }
21641 }
21642 }
21643 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021644
21645 my %GccConstants = (); # built-in GCC constants
21646 foreach my $Name (keys(%{$Constants{1}}))
21647 {
21648 if(not defined $Constants{1}{$Name}{"Header"})
21649 {
21650 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21651 delete($Constants{1}{$Name});
21652 }
21653 }
21654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021655 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021656 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021657 "TypeInfo" => $TypeInfo{1},
21658 "SymbolInfo" => $SymbolInfo{1},
21659 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021660 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021661 "SymbolVersion" => $SymVer{1},
21662 "LibraryVersion" => $Descriptor{1}{"Version"},
21663 "LibraryName" => $TargetLibraryName,
21664 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021665 "SkipTypes" => $SkipTypes{1},
21666 "SkipSymbols" => $SkipSymbols{1},
21667 "SkipNameSpaces" => $SkipNameSpaces{1},
21668 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021669 "Headers" => \%HeadersInfo,
21670 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021671 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021672 "NameSpaces" => $NestedNameSpaces{1},
21673 "Target" => $OStarget,
21674 "Arch" => getArch(1),
21675 "WordSize" => $WORD_SIZE{1},
21676 "GccVersion" => get_dumpversion($GCC_PATH),
21677 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21678 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21679 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021680 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021681 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021682 }
21683 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021684 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021686 if($ExtendedCheck)
21687 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021688 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021689 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021690 if($BinaryOnly)
21691 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021692 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021693 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021694 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021695 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021696 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021697 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21698 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021699 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021700
21701 my $ABI_DUMP = "";
21702 if($UseXML)
21703 {
21704 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021705 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021707 else
21708 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021709 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021711 if($StdOut)
21712 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021713 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021714 printMsg("INFO", "ABI dump has been generated to stdout");
21715 return;
21716 }
21717 else
21718 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021719 my ($DDir, $DName) = separate_path($DumpPath);
21720 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021721 if(not $Archive) {
21722 $DPath = $DumpPath;
21723 }
21724
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021725 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021726
21727 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021728 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021729 close(DUMP);
21730
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021731 if(not -s $DPath) {
21732 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21733 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021734 if($Archive) {
21735 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021736 }
21737
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021738 if($OutputDumpPath) {
21739 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021740 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021741 else {
21742 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21743 }
21744 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 +040021745 }
21746}
21747
21748sub quickEmptyReports()
21749{ # Quick "empty" reports
21750 # 4 times faster than merging equal dumps
21751 # NOTE: the dump contains the "LibraryVersion" attribute
21752 # if you change the version, then your dump will be different
21753 # OVERCOME: use -v1 and v2 options for comparing dumps
21754 # and don't change version in the XML descriptor (and dumps)
21755 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21756 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21757 {
21758 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21759 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21760 if($FilePath1 and $FilePath2)
21761 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021762 my $Line = readLineNum($FilePath1, 0);
21763 if($Line=~/xml/)
21764 { # XML format
21765 # is not supported yet
21766 return;
21767 }
21768
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021769 local $/ = undef;
21770
21771 open(DUMP1, $FilePath1);
21772 my $Content1 = <DUMP1>;
21773 close(DUMP1);
21774
21775 open(DUMP2, $FilePath2);
21776 my $Content2 = <DUMP2>;
21777 close(DUMP2);
21778
21779 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021780 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021781 # clean memory
21782 undef $Content2;
21783
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021784 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021785 my $ABIdump = eval($Content1);
21786
21787 # clean memory
21788 undef $Content1;
21789
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021791 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 +040021792 }
21793 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021794 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021795 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21796 }
21797 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021798 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021799 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21800 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021801 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021802 read_Libs_DumpInfo($ABIdump, 1);
21803 read_Machine_DumpInfo($ABIdump, 1);
21804 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021805
21806 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21807 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21808
21809 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21810 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21811
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021812 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21813 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21814 exitReport();
21815 }
21816 }
21817 }
21818}
21819
21820sub initLogging($)
21821{
21822 my $LibVersion = $_[0];
21823 # create log directory
21824 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21825 if($OutputLogPath{$LibVersion})
21826 { # user-defined by -log-path option
21827 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21828 }
21829 if($LogMode ne "n") {
21830 mkpath($LOG_DIR);
21831 }
21832 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021833 if($Debug)
21834 { # debug directory
21835 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021836
21837 if(not $ExtraInfo)
21838 { # enable --extra-info
21839 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021841 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021842 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021843}
21844
21845sub writeLog($$)
21846{
21847 my ($LibVersion, $Msg) = @_;
21848 if($LogMode ne "n") {
21849 appendFile($LOG_PATH{$LibVersion}, $Msg);
21850 }
21851}
21852
21853sub resetLogging($)
21854{
21855 my $LibVersion = $_[0];
21856 if($LogMode!~/a|n/)
21857 { # remove old log
21858 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021859 if($Debug) {
21860 rmtree($DEBUG_PATH{$LibVersion});
21861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021862 }
21863}
21864
21865sub printErrorLog($)
21866{
21867 my $LibVersion = $_[0];
21868 if($LogMode ne "n") {
21869 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21870 }
21871}
21872
21873sub isDump($)
21874{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021875 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21876 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021877 return $1;
21878 }
21879 return 0;
21880}
21881
21882sub isDump_U($)
21883{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021884 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021885 return $1;
21886 }
21887 return 0;
21888}
21889
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021890sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021891{
21892 # read input XML descriptors or ABI dumps
21893 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021894 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021895 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021896 if(not -e $Descriptor{1}{"Path"}) {
21897 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021900 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021901 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021902 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021903 if(not -e $Descriptor{2}{"Path"}) {
21904 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021905 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021906
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021907 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021908 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021909 and isDump($Descriptor{2}{"Path"}))
21910 { # optimization: equal ABI dumps
21911 quickEmptyReports();
21912 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021913
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021914 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021915
21916 if(isDump($Descriptor{1}{"Path"})) {
21917 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021918 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021919 else {
21920 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21921 }
21922
21923 if(isDump($Descriptor{2}{"Path"})) {
21924 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21925 }
21926 else {
21927 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021928 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021929
21930 if(not $Descriptor{1}{"Version"})
21931 { # set to default: X
21932 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021933 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021934 }
21935
21936 if(not $Descriptor{2}{"Version"})
21937 { # set to default: Y
21938 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021939 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021940 }
21941
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030021942 if(not $UsedDump{1}{"V"}) {
21943 initLogging(1);
21944 }
21945
21946 if(not $UsedDump{2}{"V"}) {
21947 initLogging(2);
21948 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021949
21950 # check input data
21951 if(not $Descriptor{1}{"Headers"}) {
21952 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021953 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021954 if(not $Descriptor{2}{"Headers"}) {
21955 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021956 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021957
21958 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021959 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021960 if(not $Descriptor{1}{"Libs"}) {
21961 exitStatus("Error", "can't find libraries info in descriptor d1");
21962 }
21963 if(not $Descriptor{2}{"Libs"}) {
21964 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021965 }
21966 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021968 if($UseDumps)
21969 { # --use-dumps
21970 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021971 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21972 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021973
21974 unlink($DumpPath1);
21975 unlink($DumpPath2);
21976
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021977 my $pid = fork();
21978 if($pid)
21979 { # dump on two CPU cores
21980 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21981 if($RelativeDirectory{1}) {
21982 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21983 }
21984 if($OutputLogPath{1}) {
21985 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21986 }
21987 if($CrossGcc) {
21988 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21989 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021990 if($Quiet)
21991 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021993 @PARAMS = (@PARAMS, "-logging-mode", "a");
21994 }
21995 elsif($LogMode and $LogMode ne "w")
21996 { # "w" is default
21997 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021998 }
21999 if($ExtendedCheck) {
22000 @PARAMS = (@PARAMS, "-extended");
22001 }
22002 if($UserLang) {
22003 @PARAMS = (@PARAMS, "-lang", $UserLang);
22004 }
22005 if($TargetVersion{1}) {
22006 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22007 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022008 if($BinaryOnly) {
22009 @PARAMS = (@PARAMS, "-binary");
22010 }
22011 if($SourceOnly) {
22012 @PARAMS = (@PARAMS, "-source");
22013 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022014 if($SortDump) {
22015 @PARAMS = (@PARAMS, "-sort");
22016 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022017 if($DumpFormat and $DumpFormat ne "perl") {
22018 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22019 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022020 if($CheckHeadersOnly) {
22021 @PARAMS = (@PARAMS, "-headers-only");
22022 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022023 if($Debug)
22024 {
22025 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022026 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022028 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022029 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022030 exit(1);
22031 }
22032 }
22033 else
22034 { # child
22035 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22036 if($RelativeDirectory{2}) {
22037 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22038 }
22039 if($OutputLogPath{2}) {
22040 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22041 }
22042 if($CrossGcc) {
22043 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22044 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022045 if($Quiet)
22046 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022047 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022048 @PARAMS = (@PARAMS, "-logging-mode", "a");
22049 }
22050 elsif($LogMode and $LogMode ne "w")
22051 { # "w" is default
22052 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022053 }
22054 if($ExtendedCheck) {
22055 @PARAMS = (@PARAMS, "-extended");
22056 }
22057 if($UserLang) {
22058 @PARAMS = (@PARAMS, "-lang", $UserLang);
22059 }
22060 if($TargetVersion{2}) {
22061 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22062 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022063 if($BinaryOnly) {
22064 @PARAMS = (@PARAMS, "-binary");
22065 }
22066 if($SourceOnly) {
22067 @PARAMS = (@PARAMS, "-source");
22068 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022069 if($SortDump) {
22070 @PARAMS = (@PARAMS, "-sort");
22071 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022072 if($DumpFormat and $DumpFormat ne "perl") {
22073 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22074 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022075 if($CheckHeadersOnly) {
22076 @PARAMS = (@PARAMS, "-headers-only");
22077 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022078 if($Debug)
22079 {
22080 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022081 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022082 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022083 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022084 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022085 exit(1);
22086 }
22087 else {
22088 exit(0);
22089 }
22090 }
22091 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022093 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022094 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22095 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022096 if($TargetTitle ne $TargetLibraryName) {
22097 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022098 }
22099 if($ShowRetVal) {
22100 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22101 }
22102 if($CrossGcc) {
22103 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22104 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022105 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22106 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022107 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022108 }
22109 if($ReportFormat and $ReportFormat ne "html")
22110 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22112 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022113 if($OutputReportPath) {
22114 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22115 }
22116 if($BinaryReportPath) {
22117 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22118 }
22119 if($SourceReportPath) {
22120 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22121 }
22122 if($LoggingPath) {
22123 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22124 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022125 if($CheckHeadersOnly) {
22126 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22127 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022128 if($BinaryOnly) {
22129 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22130 }
22131 if($SourceOnly) {
22132 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22133 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022134 if($Debug)
22135 {
22136 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22137 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022139 system("perl", $0, @CMP_PARAMS);
22140 exit($?>>8);
22141 }
22142 if(not $Descriptor{1}{"Dump"}
22143 or not $Descriptor{2}{"Dump"})
22144 { # need GCC toolchain to analyze
22145 # header files and libraries
22146 detect_default_paths("inc|lib|gcc");
22147 }
22148 if(not $Descriptor{1}{"Dump"})
22149 {
22150 if(not $CheckHeadersOnly) {
22151 readLibs(1);
22152 }
22153 if($CheckHeadersOnly) {
22154 setLanguage(1, "C++");
22155 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022156 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022157 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022158 }
22159 if(not $Descriptor{2}{"Dump"})
22160 {
22161 if(not $CheckHeadersOnly) {
22162 readLibs(2);
22163 }
22164 if($CheckHeadersOnly) {
22165 setLanguage(2, "C++");
22166 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022167 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022168 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022169 }
22170 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22171 { # support for old ABI dumps
22172 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022173 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022174 {
22175 $WORD_SIZE{1} = $WORD_SIZE{2};
22176 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22177 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022178 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022179 {
22180 $WORD_SIZE{2} = $WORD_SIZE{1};
22181 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22182 }
22183 }
22184 elsif(not $WORD_SIZE{1}
22185 and not $WORD_SIZE{2})
22186 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022187 $WORD_SIZE{1} = "4";
22188 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022189 }
22190 if($Descriptor{1}{"Dump"})
22191 { # support for old ABI dumps
22192 prepareTypes(1);
22193 }
22194 if($Descriptor{2}{"Dump"})
22195 { # support for old ABI dumps
22196 prepareTypes(2);
22197 }
22198 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22199 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22200 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022201 # process input data
22202 if($Descriptor{1}{"Headers"}
22203 and not $Descriptor{1}{"Dump"}) {
22204 readHeaders(1);
22205 }
22206 if($Descriptor{2}{"Headers"}
22207 and not $Descriptor{2}{"Dump"}) {
22208 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022209 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022210
22211 # clean memory
22212 %SystemHeaders = ();
22213 %mangled_name_gcc = ();
22214
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022215 prepareSymbols(1);
22216 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022217
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022218 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022219 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022220
22221 # Virtual Tables
22222 registerVTable(1);
22223 registerVTable(2);
22224
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022225 if(not checkDump(1, "1.22")
22226 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022227 { # support for old ABI dumps
22228 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22229 {
22230 if($ClassName=~/</)
22231 { # templates
22232 if(not defined $VirtualTable{1}{$ClassName})
22233 { # synchronize
22234 delete($VirtualTable{2}{$ClassName});
22235 }
22236 }
22237 }
22238 }
22239
22240 registerOverriding(1);
22241 registerOverriding(2);
22242
22243 setVirtFuncPositions(1);
22244 setVirtFuncPositions(2);
22245
22246 # Other
22247 addParamNames(1);
22248 addParamNames(2);
22249
22250 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022251}
22252
22253sub compareAPIs($)
22254{
22255 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022256
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022257 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022258 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022259
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022260 if($Level eq "Binary") {
22261 printMsg("INFO", "comparing ABIs ...");
22262 }
22263 else {
22264 printMsg("INFO", "comparing APIs ...");
22265 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022266
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022267 if($CheckHeadersOnly
22268 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022269 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022270 detectAdded_H($Level);
22271 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022272 }
22273 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022274 { # added/removed in libs
22275 detectAdded($Level);
22276 detectRemoved($Level);
22277 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022278
22279 mergeSymbols($Level);
22280 if(keys(%{$CheckedSymbols{$Level}})) {
22281 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022282 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022283
22284 $Cache{"mergeTypes"} = (); # free memory
22285
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022286 if($CheckHeadersOnly
22287 or $Level eq "Source")
22288 { # added/removed in headers
22289 mergeHeaders($Level);
22290 }
22291 else
22292 { # added/removed in libs
22293 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022294 }
22295}
22296
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022297sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022298{
22299 my %Opts = (
22300 "OStarget"=>$OStarget,
22301 "Debug"=>$Debug,
22302 "Quiet"=>$Quiet,
22303 "LogMode"=>$LogMode,
22304 "CheckHeadersOnly"=>$CheckHeadersOnly,
22305
22306 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022307 "GCC_PATH"=>$GCC_PATH,
22308 "TargetSysInfo"=>$TargetSysInfo,
22309 "CrossPrefix"=>$CrossPrefix,
22310 "TargetLibraryName"=>$TargetLibraryName,
22311 "CrossGcc"=>$CrossGcc,
22312 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022313 "NoStdInc"=>$NoStdInc,
22314
22315 "BinaryOnly" => $BinaryOnly,
22316 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 );
22318 return \%Opts;
22319}
22320
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022321sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022322{
22323 my %CODE_ERROR = reverse(%ERROR_CODE);
22324 return $CODE_ERROR{$_[0]};
22325}
22326
22327sub scenario()
22328{
22329 if($StdOut)
22330 { # enable quiet mode
22331 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022332 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022333 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022334 if(not $LogMode)
22335 { # default
22336 $LogMode = "w";
22337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022338 if($UserLang)
22339 { # --lang=C++
22340 $UserLang = uc($UserLang);
22341 $COMMON_LANGUAGE{1}=$UserLang;
22342 $COMMON_LANGUAGE{2}=$UserLang;
22343 }
22344 if($LoggingPath)
22345 {
22346 $OutputLogPath{1} = $LoggingPath;
22347 $OutputLogPath{2} = $LoggingPath;
22348 if($Quiet) {
22349 $COMMON_LOG_PATH = $LoggingPath;
22350 }
22351 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022352
22353 if($SkipInternalSymbols) {
22354 $SkipInternalSymbols=~s/\*/.*/g;
22355 }
22356
22357 if($SkipInternalTypes) {
22358 $SkipInternalTypes=~s/\*/.*/g;
22359 }
22360
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022361 if($Quick) {
22362 $ADD_TMPL_INSTANCES = 0;
22363 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022364 if($OutputDumpPath)
22365 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022366 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022367 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22368 }
22369 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022370 if($BinaryOnly and $SourceOnly)
22371 { # both --binary and --source
22372 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022373 if(not $CmpSystems)
22374 {
22375 $BinaryOnly = 0;
22376 $SourceOnly = 0;
22377 }
22378
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022379 $DoubleReport = 1;
22380 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022381
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022382 if($OutputReportPath)
22383 { # --report-path
22384 $DoubleReport = 0;
22385 $JoinReport = 1;
22386 }
22387 }
22388 elsif($BinaryOnly or $SourceOnly)
22389 { # --binary or --source
22390 $DoubleReport = 0;
22391 $JoinReport = 0;
22392 }
22393 if($UseXML)
22394 { # --xml option
22395 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022396 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022398 if($ReportFormat)
22399 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022400 $ReportFormat = lc($ReportFormat);
22401 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022402 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022403 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022404 if($ReportFormat eq "htm")
22405 { # HTM == HTML
22406 $ReportFormat = "html";
22407 }
22408 elsif($ReportFormat eq "xml")
22409 { # --report-format=XML equal to --xml
22410 $UseXML = 1;
22411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022412 }
22413 else
22414 { # default: HTML
22415 $ReportFormat = "html";
22416 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022417 if($DumpFormat)
22418 { # validate
22419 $DumpFormat = lc($DumpFormat);
22420 if($DumpFormat!~/\A(xml|perl)\Z/) {
22421 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22422 }
22423 if($DumpFormat eq "xml")
22424 { # --dump-format=XML equal to --xml
22425 $UseXML = 1;
22426 }
22427 }
22428 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022429 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022430 $DumpFormat = "perl";
22431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022432 if($Quiet and $LogMode!~/a|n/)
22433 { # --quiet log
22434 if(-f $COMMON_LOG_PATH) {
22435 unlink($COMMON_LOG_PATH);
22436 }
22437 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022438 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022439 $CheckUndefined = 1;
22440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022441 if($TestTool and $UseDumps)
22442 { # --test && --use-dumps == --test-dump
22443 $TestDump = 1;
22444 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022445 if($Tolerant)
22446 { # enable all
22447 $Tolerance = 1234;
22448 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022449 if($Help)
22450 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022451 HELP_MESSAGE();
22452 exit(0);
22453 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022454 if($InfoMsg)
22455 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022456 INFO_MESSAGE();
22457 exit(0);
22458 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022459 if($ShowVersion)
22460 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022461 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 +040022462 exit(0);
22463 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022464 if($DumpVersion)
22465 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022466 printMsg("INFO", $TOOL_VERSION);
22467 exit(0);
22468 }
22469 if($ExtendedCheck) {
22470 $CheckHeadersOnly = 1;
22471 }
22472 if($SystemRoot_Opt)
22473 { # user defined root
22474 if(not -e $SystemRoot_Opt) {
22475 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22476 }
22477 $SystemRoot = $SystemRoot_Opt;
22478 $SystemRoot=~s/[\/]+\Z//g;
22479 if($SystemRoot) {
22480 $SystemRoot = get_abs_path($SystemRoot);
22481 }
22482 }
22483 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022484
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022485 if($SortDump)
22486 {
22487 $Data::Dumper::Useperl = 1;
22488 $Data::Dumper::Sortkeys = \&dump_sorting;
22489 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022490
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022491 if($TargetLibsPath)
22492 {
22493 if(not -f $TargetLibsPath) {
22494 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22495 }
22496 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22497 $TargetLibs{$Lib} = 1;
22498 }
22499 }
22500 if($TargetHeadersPath)
22501 { # --headers-list
22502 if(not -f $TargetHeadersPath) {
22503 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22504 }
22505 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22506 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022507 $TargetHeaders{1}{get_filename($Header)} = 1;
22508 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022509 }
22510 }
22511 if($TargetHeader)
22512 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022513 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22514 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022515 }
22516 if($TestTool
22517 or $TestDump)
22518 { # --test, --test-dump
22519 detect_default_paths("bin|gcc"); # to compile libs
22520 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022521 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022522 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022523 exit(0);
22524 }
22525 if($DumpSystem)
22526 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022527
22528 if(not $TargetSysInfo) {
22529 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22530 }
22531
22532 if(not -d $TargetSysInfo) {
22533 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22534 }
22535
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022536 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022537 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022538 { # system XML descriptor
22539 if(not -f $DumpSystem) {
22540 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22541 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022542
22543 my $SDesc = readFile($DumpSystem);
22544 if(my $RelDir = $RelativeDirectory{1}) {
22545 $SDesc =~ s/{RELPATH}/$RelDir/g;
22546 }
22547
22548 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022549 foreach (@{$Ret->{"Tools"}})
22550 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022551 push_U($SystemPaths{"bin"}, $_);
22552 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022553 }
22554 if($Ret->{"CrossPrefix"}) {
22555 $CrossPrefix = $Ret->{"CrossPrefix"};
22556 }
22557 }
22558 elsif($SystemRoot_Opt)
22559 { # -sysroot "/" option
22560 # default target: /usr/lib, /usr/include
22561 # search libs: /usr/lib and /lib
22562 if(not -e $SystemRoot."/usr/lib") {
22563 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22564 }
22565 if(not -e $SystemRoot."/lib") {
22566 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22567 }
22568 if(not -e $SystemRoot."/usr/include") {
22569 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22570 }
22571 readSystemDescriptor("
22572 <name>
22573 $DumpSystem
22574 </name>
22575 <headers>
22576 $SystemRoot/usr/include
22577 </headers>
22578 <libs>
22579 $SystemRoot/usr/lib
22580 </libs>
22581 <search_libs>
22582 $SystemRoot/lib
22583 </search_libs>");
22584 }
22585 else {
22586 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22587 }
22588 detect_default_paths("bin|gcc"); # to check symbols
22589 if($OStarget eq "windows")
22590 { # to run dumpbin.exe
22591 # and undname.exe
22592 check_win32_env();
22593 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022594 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022595 exit(0);
22596 }
22597 if($CmpSystems)
22598 { # --cmp-systems
22599 detect_default_paths("bin"); # to extract dumps
22600 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022601 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022602 exit(0);
22603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022604 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022605 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022606 }
22607 else
22608 { # validate library name
22609 if($TargetLibraryName=~/[\*\/\\]/) {
22610 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22611 }
22612 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022613 if(not $TargetTitle) {
22614 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022615 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022617 if($SymbolsListPath)
22618 {
22619 if(not -f $SymbolsListPath) {
22620 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22621 }
22622 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22623 $SymbolsList{$Interface} = 1;
22624 }
22625 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022626 if($TypesListPath)
22627 {
22628 if(not -f $TypesListPath) {
22629 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22630 }
22631 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22632 $TypesList{$Type} = 1;
22633 }
22634 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022635 if($SkipSymbolsListPath)
22636 {
22637 if(not -f $SkipSymbolsListPath) {
22638 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22639 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022640 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22641 {
22642 $SkipSymbols{1}{$Interface} = 1;
22643 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022644 }
22645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022646 if($SkipHeadersPath)
22647 {
22648 if(not -f $SkipHeadersPath) {
22649 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22650 }
22651 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022652 { # register for both versions
22653 $SkipHeadersList{1}{$Path} = 1;
22654 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022655 my ($CPath, $Type) = classifyPath($Path);
22656 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022657 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022658 }
22659 }
22660 if($ParamNamesPath)
22661 {
22662 if(not -f $ParamNamesPath) {
22663 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22664 }
22665 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22666 {
22667 if($Line=~s/\A(\w+)\;//)
22668 {
22669 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022670 if($Line=~/;(\d+);/)
22671 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022672 while($Line=~s/(\d+);(\w+)//) {
22673 $AddIntParams{$Interface}{$1}=$2;
22674 }
22675 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022676 else
22677 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022678 my $Num = 0;
22679 foreach my $Name (split(/;/, $Line)) {
22680 $AddIntParams{$Interface}{$Num++}=$Name;
22681 }
22682 }
22683 }
22684 }
22685 }
22686 if($AppPath)
22687 {
22688 if(not -f $AppPath) {
22689 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22690 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022691
22692 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022693 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022694 $SymbolsList_App{$Interface} = 1;
22695 }
22696 }
22697 if($DumpAPI)
22698 { # --dump-abi
22699 # make an API dump
22700 create_ABI_Dump();
22701 exit($COMPILE_ERRORS);
22702 }
22703 # default: compare APIs
22704 # -d1 <path>
22705 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022706 compareInit();
22707 if($JoinReport or $DoubleReport)
22708 {
22709 compareAPIs("Binary");
22710 compareAPIs("Source");
22711 }
22712 elsif($BinaryOnly) {
22713 compareAPIs("Binary");
22714 }
22715 elsif($SourceOnly) {
22716 compareAPIs("Source");
22717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022718 exitReport();
22719}
22720
22721scenario();