blob: 4cffd9de160b7f2351867bac657af8abcb2ef1ee [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03003# ABI Compliance Checker (ABICC) 1.99.21
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
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +03009# Copyright (C) 2012-2016 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 Ponomarenko8a4c3f82016-02-21 03:45:16 +030024# - ABI Dumper (0.99.15 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040025#
26# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040027# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040028# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040029#
30# MS Windows
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +040031# - MinGW (3.0-4.7, 4.8.3, 4.9 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040032# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040033# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040034# - Sigcheck v1.71 or newer
35# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040036# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040037# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040038# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
39#
40# This program is free software: you can redistribute it and/or modify
41# it under the terms of the GNU General Public License or the GNU Lesser
42# General Public License as published by the Free Software Foundation.
43#
44# This program is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47# GNU General Public License for more details.
48#
49# You should have received a copy of the GNU General Public License
50# and the GNU Lesser General Public License along with this program.
51# If not, see <http://www.gnu.org/licenses/>.
52###########################################################################
53use Getopt::Long;
54Getopt::Long::Configure ("posix_default", "no_ignore_case");
55use File::Path qw(mkpath rmtree);
56use File::Temp qw(tempdir);
57use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040058use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040059use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040060use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040061use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040062
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030063my $TOOL_VERSION = "1.99.21";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040064my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040065my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040066my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040067my $OSgroup = get_OSgroup();
68my $ORIG_DIR = cwd();
69my $TMP_DIR = tempdir(CLEANUP=>1);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030070my $LOCALE = "C.UTF-8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071
72# Internal modules
73my $MODULES_DIR = get_Modules();
74push(@INC, get_dirname($MODULES_DIR));
75# Rules DB
76my %RULES_PATH = (
77 "Binary" => $MODULES_DIR."/RulesBin.xml",
78 "Source" => $MODULES_DIR."/RulesSrc.xml");
79
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030080my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040081$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030082$AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030083%RelativeDirectory, $TargetTitle, $TestDump, $LoggingPath,
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030084%TargetVersion, $InfoMsg, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040085$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
86$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
87$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040088$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040089$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030090$SourceReportPath, $UseXML, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040091$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030092$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat,
93$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040095
96my $CmdName = get_filename($0);
97my %OS_LibExt = (
98 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040099 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400100 "macos"=>"dylib",
101 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "symbian"=>"dso",
103 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400104 },
105 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400106 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "symbian"=>"lib",
109 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 }
111);
112
113my %OS_Archive = (
114 "windows"=>"zip",
115 "default"=>"tar.gz"
116);
117
118my %ERROR_CODE = (
119 # Compatible verdict
120 "Compatible"=>0,
121 "Success"=>0,
122 # Incompatible verdict
123 "Incompatible"=>1,
124 # Undifferentiated error code
125 "Error"=>2,
126 # System command is not found
127 "Not_Found"=>3,
128 # Cannot access input files
129 "Access_Error"=>4,
130 # Cannot compile header files
131 "Cannot_Compile"=>5,
132 # Header compiled with errors
133 "Compile_Error"=>6,
134 # Invalid input ABI dump
135 "Invalid_Dump"=>7,
136 # Incompatible version of ABI dump
137 "Dump_Version"=>8,
138 # Cannot find a module
139 "Module_Error"=>9,
140 # Empty intersection between
141 # headers and shared objects
142 "Empty_Intersection"=>10,
143 # Empty set of symbols in headers
144 "Empty_Set"=>11
145);
146
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300147my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400148
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400149my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300151Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400152License: GNU LGPL or GNU GPL
153
154Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400155Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400156
157OLD.xml and NEW.xml are XML-descriptors:
158
159 <version>
160 1.0
161 </version>
162
163 <headers>
164 /path/to/headers/
165 </headers>
166
167 <libs>
168 /path/to/libraries/
169 </libs>
170
171More info: $CmdName --help\n";
172
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400173if($#ARGV==-1)
174{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400175 printMsg("INFO", $ShortUsage);
176 exit(0);
177}
178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400179GetOptions("h|help!" => \$Help,
180 "i|info!" => \$InfoMsg,
181 "v|version!" => \$ShowVersion,
182 "dumpversion!" => \$DumpVersion,
183# general options
184 "l|lib|library=s" => \$TargetLibraryName,
185 "d1|old|o=s" => \$Descriptor{1}{"Path"},
186 "d2|new|n=s" => \$Descriptor{2}{"Path"},
187 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400188# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189 "app|application=s" => \$AppPath,
190 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400191 "gcc-path|cross-gcc=s" => \$CrossGcc,
192 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
193 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300195 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
196 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400197 "s|strict!" => \$StrictCompat,
198 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300199 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400200 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300201 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400202 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400203 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400204 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400205 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400206 "show-retval!" => \$ShowRetVal,
207 "use-dumps!" => \$UseDumps,
208 "nostdinc!" => \$NoStdInc,
209 "dump-system=s" => \$DumpSystem,
210 "sysinfo=s" => \$TargetSysInfo,
211 "cmp-systems!" => \$CmpSystems,
212 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400213 "ext|extended!" => \$ExtendedCheck,
214 "q|quiet!" => \$Quiet,
215 "stdout!" => \$StdOut,
216 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400217 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400218 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400219 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400220 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400221 "binary|bin|abi!" => \$BinaryOnly,
222 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400223 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300224 "count-symbols=s" => \$CountSymbols,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400225# other options
226 "test!" => \$TestTool,
227 "test-dump!" => \$TestDump,
228 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400229 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400230 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400231 "p|params=s" => \$ParamNamesPath,
232 "relpath1|relpath=s" => \$RelativeDirectory{1},
233 "relpath2=s" => \$RelativeDirectory{2},
234 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400235 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400236 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400237 "bin-report-path=s" => \$BinaryReportPath,
238 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400239 "log-path=s" => \$LoggingPath,
240 "log1-path=s" => \$OutputLogPath{1},
241 "log2-path=s" => \$OutputLogPath{2},
242 "logging-mode=s" => \$LogMode,
243 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300244 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400246 "extra-info=s" => \$ExtraInfo,
247 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400248 "force!" => \$Force,
249 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400250 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400251 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400252 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400253 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300254 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
255 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300256 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400257) or ERR_MESSAGE();
258
259sub ERR_MESSAGE()
260{
261 printMsg("INFO", "\n".$ShortUsage);
262 exit($ERROR_CODE{"Error"});
263}
264
265my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
266my $SLIB_TYPE = $LIB_TYPE;
267if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
268{ # show as "shared" library
269 $SLIB_TYPE = "shared";
270}
271my $LIB_EXT = getLIB_EXT($OSgroup);
272my $AR_EXT = getAR_EXT($OSgroup);
273my $BYTE_SIZE = 8;
274my $COMMON_LOG_PATH = "logs/run.log";
275
276my $HelpMessage="
277NAME:
278 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400279 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400280
281DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400282 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400283 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
284 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
285 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
286 and/or source-level compatibility: changes in calling stack, v-table changes,
287 removed symbols, renamed fields, etc. Binary incompatibility may result in
288 crashing or incorrect behavior of applications built with an old version of
289 a library if they run on a new one. Source incompatibility may result in
290 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400291
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400292 The tool is intended for developers of software libraries and maintainers
293 of operating systems who are interested in ensuring backward compatibility,
294 i.e. allow old applications to run or to be recompiled with newer library
295 versions.
296
297 Also the tool can be used by ISVs for checking applications portability to
298 new library versions. Found issues can be taken into account when adapting
299 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400300
301 This tool is free software: you can redistribute it and/or modify it
302 under the terms of the GNU LGPL or GNU GPL.
303
304USAGE:
305 $CmdName [options]
306
307EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400308 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400309
310 OLD.xml and NEW.xml are XML-descriptors:
311
312 <version>
313 1.0
314 </version>
315
316 <headers>
317 /path1/to/header(s)/
318 /path2/to/header(s)/
319 ...
320 </headers>
321
322 <libs>
323 /path1/to/library(ies)/
324 /path2/to/library(ies)/
325 ...
326 </libs>
327
328INFORMATION OPTIONS:
329 -h|-help
330 Print this help.
331
332 -i|-info
333 Print complete info.
334
335 -v|-version
336 Print version information.
337
338 -dumpversion
339 Print the tool version ($TOOL_VERSION) and don't do anything else.
340
341GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400342 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400343 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400344
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400345 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400346 Descriptor of 1st (old) library version.
347 It may be one of the following:
348
349 1. XML-descriptor (VERSION.xml file):
350
351 <version>
352 1.0
353 </version>
354
355 <headers>
356 /path1/to/header(s)/
357 /path2/to/header(s)/
358 ...
359 </headers>
360
361 <libs>
362 /path1/to/library(ies)/
363 /path2/to/library(ies)/
364 ...
365 </libs>
366
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300367 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400368
369 2. ABI dump generated by -dump option
370 3. Directory with headers and/or $SLIB_TYPE libraries
371 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400372
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300373 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400374 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400375
376 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400377 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400378
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400379 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400380 Descriptor of 2nd (new) library version.
381
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400382 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400383 Create library ABI dump for the input XML descriptor. You can
384 transfer it anywhere and pass instead of the descriptor. Also
385 it can be used for debugging the tool.
386
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300387 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400388
389sub HELP_MESSAGE() {
390 printMsg("INFO", $HelpMessage."
391MORE INFO:
392 $CmdName --info\n");
393}
394
395sub INFO_MESSAGE()
396{
397 printMsg("INFO", "$HelpMessage
398EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400399 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300400 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400401 for portability to the new library version.
402
403 -static-libs
404 Check static libraries instead of the shared ones. The <libs> section
405 of the XML-descriptor should point to static libraries location.
406
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300407 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408 Path to the cross GCC compiler to use instead of the usual (host) GCC.
409
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300410 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400411 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300412
413 -gcc-options OPTS
414 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400416 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400418 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400420 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200422 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400423
424 In general case you should specify it in the XML-descriptor:
425 <version>
426 VERSION
427 </version>
428
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400429 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400430 Specify 2nd library version outside the descriptor.
431
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400432 -vnum NUM
433 Specify the library version in the generated ABI dump. The <version> section
434 of the input XML descriptor will be overwritten in this case.
435
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400436 -s|-strict
437 Treat all compatibility warnings as problems. Add a number of \"Low\"
438 severity problems to the return value of the tool.
439
440 -headers-only
441 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
442 provide a low quality compatibility report with false positives and
443 without detecting of added/removed symbols.
444
445 Alternatively you can write \"none\" word to the <libs> section
446 in the XML-descriptor:
447 <libs>
448 none
449 </libs>
450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400451 -show-retval
452 Show the symbol's return type in the report.
453
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400454 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300455 This option allows to specify a file with a list of symbols (mangled
456 names in C++) that should be checked. Other symbols will not be checked.
457
458 -types-list PATH
459 This option allows to specify a file with a list of types that should
460 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400461
462 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300463 The list of symbols that should not be checked.
464
465 -skip-types PATH
466 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400467
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400468 -headers-list PATH
469 The file with a list of headers, that should be checked/dumped.
470
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400471 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400472 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400473
474 -header NAME
475 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400476
477 -use-dumps
478 Make dumps for two versions of a library and compare dumps. This should
479 increase the performance of the tool and decrease the system memory usage.
480
481 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400482 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400483
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400484 -dump-system NAME -sysroot DIR
485 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400486 create XML descriptors and make ABI dumps for each library. The result
487 set of ABI dumps can be compared (--cmp-systems) with the other one
488 created for other version of operating system in order to check them for
489 compatibility. Do not forget to specify -cross-gcc option if your target
490 system requires some specific version of GCC compiler (different from
491 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400492 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400493
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400494 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495 The same as the previous option but takes an XML descriptor of the target
496 system as input, where you should describe it:
497
498 /* Primary sections */
499
500 <name>
501 /* Name of the system */
502 </name>
503
504 <headers>
505 /* The list of paths to header files and/or
506 directories with header files, one per line */
507 </headers>
508
509 <libs>
510 /* The list of paths to shared libraries and/or
511 directories with shared libraries, one per line */
512 </libs>
513
514 /* Optional sections */
515
516 <search_headers>
517 /* List of directories to be searched
518 for header files to automatically
519 generate include paths, one per line */
520 </search_headers>
521
522 <search_libs>
523 /* List of directories to be searched
524 for shared libraries to resolve
525 dependencies, one per line */
526 </search_libs>
527
528 <tools>
529 /* List of directories with tools used
530 for analysis (GCC toolchain), one per line */
531 </tools>
532
533 <cross_prefix>
534 /* GCC toolchain prefix.
535 Examples:
536 arm-linux-gnueabi
537 arm-none-symbianelf */
538 </cross_prefix>
539
540 <gcc_options>
541 /* Additional GCC options, one per line */
542 </gcc_options>
543
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400544 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300545 This option should be used with -dump-system option to dump
546 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400547
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 Ponomarenko447e7d52016-05-20 19:12:20 +0300615
616 -count-symbols PATH
617 Count total public symbols in the ABI dump.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400618
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400619OTHER OPTIONS:
620 -test
621 Run internal tests. Create two binary incompatible versions of a sample
622 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300623 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400624
625 -test-dump
626 Test ability to create, read and compare ABI dumps.
627
628 -debug
629 Debugging mode. Print debug info on the screen. Save intermediate
630 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400631 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400632
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400633 Also consider using --dump option for debugging the tool.
634
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400635 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400636 If your header files are written in C language and can be compiled
637 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
638 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400639
640 -cpp-incompatible
641 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400642
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400643 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400644 Path to file with the function parameter names. It can be used
645 for improving report view if the library header files have no
646 parameter names. File format:
647
648 func1;param1;param2;param3 ...
649 func2;param1;param2;param3 ...
650 ...
651
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400652 -relpath PATH
653 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400654 for dumping the library ABI (see -dump option).
655
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400656 -relpath1 PATH
657 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400658
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400659 -relpath2 PATH
660 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400663 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400664 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400665 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400666
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400667 -sort
668 Enable sorting of data in ABI dumps.
669
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400671 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400672 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400673 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400674
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400676 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400681 Path to \"Source\" compatibility report.
682 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400686 Log path for all messages.
687 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691 Log path for 1st version of a library.
692 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696 Log path for 2nd version of a library.
697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Change logging mode.
702 Modes:
703 w - overwrite old logs (default)
704 a - append old logs
705 n - do not write any logs
706
707 -list-affected
708 Generate file with the list of incompatible
709 symbols beside the HTML compatibility report.
710 Use 'c++filt \@file' command from GNU binutils
711 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400712 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400713 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400714 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717 The component name in the title and summary of the HTML report.
718 Default:
719 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300720
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300721 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400722 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400723 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400724
725 -extra-info DIR
726 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400727
728 -extra-dump
729 Create extended ABI dump containing all symbols
730 from the translation unit.
731
732 -force
733 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400734
735 -tolerance LEVEL
736 Apply a set of heuristics to successfully compile input
737 header files. You can enable several tolerance levels by
738 joining them into one string (e.g. 13, 124, etc.).
739 Levels:
740 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
741 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
742 3 - skip headers that iclude non-Linux headers
743 4 - skip headers included by others
744
745 -tolerant
746 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400747
748 -check
749 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400750
751 -quick
752 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400753
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300754 -skip-internal-symbols PATTERN
755 Do not check symbols matched by the pattern.
756
757 -skip-internal-types PATTERN
758 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300759
760 -check-private-abi
761 Check data types from the private part of the ABI when
762 comparing ABI dumps created by the ABI Dumper tool with
763 use of the -public-headers option.
764
765 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400767REPORT:
768 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400769 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400770
771 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400772 logs/LIB_NAME/V1/log.txt
773 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400774
775EXIT CODES:
776 0 - Compatible. The tool has run without any errors.
777 non-zero - Incompatible or the tool has run with errors.
778
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400779MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300780 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400781}
782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400783my %Operator_Indication = (
784 "not" => "~",
785 "assign" => "=",
786 "andassign" => "&=",
787 "orassign" => "|=",
788 "xorassign" => "^=",
789 "or" => "|",
790 "xor" => "^",
791 "addr" => "&",
792 "and" => "&",
793 "lnot" => "!",
794 "eq" => "==",
795 "ne" => "!=",
796 "lt" => "<",
797 "lshift" => "<<",
798 "lshiftassign" => "<<=",
799 "rshiftassign" => ">>=",
800 "call" => "()",
801 "mod" => "%",
802 "modassign" => "%=",
803 "subs" => "[]",
804 "land" => "&&",
805 "lor" => "||",
806 "rshift" => ">>",
807 "ref" => "->",
808 "le" => "<=",
809 "deref" => "*",
810 "mult" => "*",
811 "preinc" => "++",
812 "delete" => " delete",
813 "vecnew" => " new[]",
814 "vecdelete" => " delete[]",
815 "predec" => "--",
816 "postinc" => "++",
817 "postdec" => "--",
818 "plusassign" => "+=",
819 "plus" => "+",
820 "minus" => "-",
821 "minusassign" => "-=",
822 "gt" => ">",
823 "ge" => ">=",
824 "new" => " new",
825 "multassign" => "*=",
826 "divassign" => "/=",
827 "div" => "/",
828 "neg" => "-",
829 "pos" => "+",
830 "memref" => "->*",
831 "compound" => "," );
832
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400833my %UnknownOperator;
834
835my %NodeType= (
836 "array_type" => "Array",
837 "binfo" => "Other",
838 "boolean_type" => "Intrinsic",
839 "complex_type" => "Intrinsic",
840 "const_decl" => "Other",
841 "enumeral_type" => "Enum",
842 "field_decl" => "Other",
843 "function_decl" => "Other",
844 "function_type" => "FunctionType",
845 "identifier_node" => "Other",
846 "integer_cst" => "Other",
847 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400848 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400849 "method_type" => "MethodType",
850 "namespace_decl" => "Other",
851 "parm_decl" => "Other",
852 "pointer_type" => "Pointer",
853 "real_cst" => "Other",
854 "real_type" => "Intrinsic",
855 "record_type" => "Struct",
856 "reference_type" => "Ref",
857 "string_cst" => "Other",
858 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400859 "template_type_parm" => "TemplateParam",
860 "typename_type" => "TypeName",
861 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400862 "tree_list" => "Other",
863 "tree_vec" => "Other",
864 "type_decl" => "Other",
865 "union_type" => "Union",
866 "var_decl" => "Other",
867 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400868 "nop_expr" => "Other", #
869 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400870 "offset_type" => "Other" );
871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400872my %CppKeywords_C = map {$_=>1} (
873 # C++ 2003 keywords
874 "public",
875 "protected",
876 "private",
877 "default",
878 "template",
879 "new",
880 #"asm",
881 "dynamic_cast",
882 "auto",
883 "try",
884 "namespace",
885 "typename",
886 "using",
887 "reinterpret_cast",
888 "friend",
889 "class",
890 "virtual",
891 "const_cast",
892 "mutable",
893 "static_cast",
894 "export",
895 # C++0x keywords
896 "noexcept",
897 "nullptr",
898 "constexpr",
899 "static_assert",
900 "explicit",
901 # cannot be used as a macro name
902 # as it is an operator in C++
903 "and",
904 #"and_eq",
905 "not",
906 #"not_eq",
907 "or"
908 #"or_eq",
909 #"bitand",
910 #"bitor",
911 #"xor",
912 #"xor_eq",
913 #"compl"
914);
915
916my %CppKeywords_F = map {$_=>1} (
917 "delete",
918 "catch",
919 "alignof",
920 "thread_local",
921 "decltype",
922 "typeid"
923);
924
925my %CppKeywords_O = map {$_=>1} (
926 "bool",
927 "register",
928 "inline",
929 "operator"
930);
931
932my %CppKeywords_A = map {$_=>1} (
933 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400934 "throw",
935 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400936);
937
938foreach (keys(%CppKeywords_C),
939keys(%CppKeywords_F),
940keys(%CppKeywords_O)) {
941 $CppKeywords_A{$_}=1;
942}
943
944# Header file extensions as described by gcc
945my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
946
947my %IntrinsicMangling = (
948 "void" => "v",
949 "bool" => "b",
950 "wchar_t" => "w",
951 "char" => "c",
952 "signed char" => "a",
953 "unsigned char" => "h",
954 "short" => "s",
955 "unsigned short" => "t",
956 "int" => "i",
957 "unsigned int" => "j",
958 "long" => "l",
959 "unsigned long" => "m",
960 "long long" => "x",
961 "__int64" => "x",
962 "unsigned long long" => "y",
963 "__int128" => "n",
964 "unsigned __int128" => "o",
965 "float" => "f",
966 "double" => "d",
967 "long double" => "e",
968 "__float80" => "e",
969 "__float128" => "g",
970 "..." => "z"
971);
972
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400973my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
974
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400975my %StdcxxMangling = (
976 "3std"=>"St",
977 "3std9allocator"=>"Sa",
978 "3std12basic_string"=>"Sb",
979 "3std12basic_stringIcE"=>"Ss",
980 "3std13basic_istreamIcE"=>"Si",
981 "3std13basic_ostreamIcE"=>"So",
982 "3std14basic_iostreamIcE"=>"Sd"
983);
984
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400985my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400986my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
987
988my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400989my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400991my %ConstantSuffix = (
992 "unsigned int"=>"u",
993 "long"=>"l",
994 "unsigned long"=>"ul",
995 "long long"=>"ll",
996 "unsigned long long"=>"ull"
997);
998
999my %ConstantSuffixR =
1000reverse(%ConstantSuffix);
1001
1002my %OperatorMangling = (
1003 "~" => "co",
1004 "=" => "aS",
1005 "|" => "or",
1006 "^" => "eo",
1007 "&" => "an",#ad (addr)
1008 "==" => "eq",
1009 "!" => "nt",
1010 "!=" => "ne",
1011 "<" => "lt",
1012 "<=" => "le",
1013 "<<" => "ls",
1014 "<<=" => "lS",
1015 ">" => "gt",
1016 ">=" => "ge",
1017 ">>" => "rs",
1018 ">>=" => "rS",
1019 "()" => "cl",
1020 "%" => "rm",
1021 "[]" => "ix",
1022 "&&" => "aa",
1023 "||" => "oo",
1024 "*" => "ml",#de (deref)
1025 "++" => "pp",#
1026 "--" => "mm",#
1027 "new" => "nw",
1028 "delete" => "dl",
1029 "new[]" => "na",
1030 "delete[]" => "da",
1031 "+=" => "pL",
1032 "+" => "pl",#ps (pos)
1033 "-" => "mi",#ng (neg)
1034 "-=" => "mI",
1035 "*=" => "mL",
1036 "/=" => "dV",
1037 "&=" => "aN",
1038 "|=" => "oR",
1039 "%=" => "rM",
1040 "^=" => "eO",
1041 "/" => "dv",
1042 "->*" => "pm",
1043 "->" => "pt",#rf (ref)
1044 "," => "cm",
1045 "?" => "qu",
1046 "." => "dt",
1047 "sizeof"=> "sz"#st
1048);
1049
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001050my %Intrinsic_Keywords = map {$_=>1} (
1051 "true",
1052 "false",
1053 "_Bool",
1054 "_Complex",
1055 "const",
1056 "int",
1057 "long",
1058 "void",
1059 "short",
1060 "float",
1061 "volatile",
1062 "restrict",
1063 "unsigned",
1064 "signed",
1065 "char",
1066 "double",
1067 "class",
1068 "struct",
1069 "union",
1070 "enum"
1071);
1072
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001073my %GlibcHeader = map {$_=>1} (
1074 "aliases.h",
1075 "argp.h",
1076 "argz.h",
1077 "assert.h",
1078 "cpio.h",
1079 "ctype.h",
1080 "dirent.h",
1081 "envz.h",
1082 "errno.h",
1083 "error.h",
1084 "execinfo.h",
1085 "fcntl.h",
1086 "fstab.h",
1087 "ftw.h",
1088 "glob.h",
1089 "grp.h",
1090 "iconv.h",
1091 "ifaddrs.h",
1092 "inttypes.h",
1093 "langinfo.h",
1094 "limits.h",
1095 "link.h",
1096 "locale.h",
1097 "malloc.h",
1098 "math.h",
1099 "mntent.h",
1100 "monetary.h",
1101 "nl_types.h",
1102 "obstack.h",
1103 "printf.h",
1104 "pwd.h",
1105 "regex.h",
1106 "sched.h",
1107 "search.h",
1108 "setjmp.h",
1109 "shadow.h",
1110 "signal.h",
1111 "spawn.h",
1112 "stdarg.h",
1113 "stdint.h",
1114 "stdio.h",
1115 "stdlib.h",
1116 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001117 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001118 "tar.h",
1119 "termios.h",
1120 "time.h",
1121 "ulimit.h",
1122 "unistd.h",
1123 "utime.h",
1124 "wchar.h",
1125 "wctype.h",
1126 "wordexp.h" );
1127
1128my %GlibcDir = map {$_=>1} (
1129 "arpa",
1130 "bits",
1131 "gnu",
1132 "netinet",
1133 "net",
1134 "nfs",
1135 "rpc",
1136 "sys",
1137 "linux" );
1138
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001139my %WinHeaders = map {$_=>1} (
1140 "dos.h",
1141 "process.h",
1142 "winsock.h",
1143 "config-win.h",
1144 "mem.h",
1145 "windows.h",
1146 "winsock2.h",
1147 "crtdbg.h",
1148 "ws2tcpip.h"
1149);
1150
1151my %ObsoleteHeaders = map {$_=>1} (
1152 "iostream.h",
1153 "fstream.h"
1154);
1155
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001156my %AlienHeaders = map {$_=>1} (
1157 # Solaris
1158 "thread.h",
1159 "sys/atomic.h",
1160 # HPUX
1161 "sys/stream.h",
1162 # Symbian
1163 "AknDoc.h",
1164 # Atari ST
1165 "ext.h",
1166 "tos.h",
1167 # MS-DOS
1168 "alloc.h",
1169 # Sparc
1170 "sys/atomic.h"
1171);
1172
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001173my %ConfHeaders = map {$_=>1} (
1174 "atomic",
1175 "conf.h",
1176 "config.h",
1177 "configure.h",
1178 "build.h",
1179 "setup.h"
1180);
1181
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001182my %LocalIncludes = map {$_=>1} (
1183 "/usr/local/include",
1184 "/usr/local" );
1185
1186my %OS_AddPath=(
1187# These paths are needed if the tool cannot detect them automatically
1188 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001189 "include"=>[
1190 "/Library",
1191 "/Developer/usr/include"
1192 ],
1193 "lib"=>[
1194 "/Library",
1195 "/Developer/usr/lib"
1196 ],
1197 "bin"=>[
1198 "/Developer/usr/bin"
1199 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001200 },
1201 "beos"=>{
1202 # Haiku has GCC 2.95.3 by default
1203 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001204 "include"=>[
1205 "/boot/common",
1206 "/boot/develop"
1207 ],
1208 "lib"=>[
1209 "/boot/common/lib",
1210 "/boot/system/lib",
1211 "/boot/apps"
1212 ],
1213 "bin"=>[
1214 "/boot/common/bin",
1215 "/boot/system/bin",
1216 "/boot/develop/abi"
1217 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001219);
1220
1221my %Slash_Type=(
1222 "default"=>"/",
1223 "windows"=>"\\"
1224);
1225
1226my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1227
1228# Global Variables
1229my %COMMON_LANGUAGE=(
1230 1 => "C",
1231 2 => "C" );
1232
1233my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001234my $MAX_CPPFILT_FILE_SIZE = 50000;
1235my $CPPFILT_SUPPORT_FILE;
1236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001237my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1238
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001239my $STDCXX_TESTING = 0;
1240my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001241my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001242
1243my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001244my $CheckUndefined = 0;
1245
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001246my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001247if($TargetComponent_Opt) {
1248 $TargetComponent = lc($TargetComponent_Opt);
1249}
1250else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001251{ # default: library
1252 # other components: header, system, ...
1253 $TargetComponent = "library";
1254}
1255
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001256my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001258my $SystemRoot;
1259
1260my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001261my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001262my %LOG_PATH;
1263my %DEBUG_PATH;
1264my %Cache;
1265my %LibInfo;
1266my $COMPILE_ERRORS = 0;
1267my %CompilerOptions;
1268my %CheckedDyLib;
1269my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1270
1271# Constants (#defines)
1272my %Constants;
1273my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001274my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001275
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001276# Extra Info
1277my %SymbolHeader;
1278my %KnownLibs;
1279
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001280# Templates
1281my %TemplateInstance;
1282my %BasicTemplate;
1283my %TemplateArg;
1284my %TemplateDecl;
1285my %TemplateMap;
1286
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001287# Types
1288my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001289my %SkipTypes = (
1290 "1"=>{},
1291 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001292my %CheckedTypes;
1293my %TName_Tid;
1294my %EnumMembName_Id;
1295my %NestedNameSpaces = (
1296 "1"=>{},
1297 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001298my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001299my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300my %ClassVTable;
1301my %ClassVTable_Content;
1302my %VTableClass;
1303my %AllocableClass;
1304my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001305my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001306my %Class_SubClasses;
1307my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001308my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001309my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001310
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001311my %CheckedTypeInfo;
1312
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001313# Typedefs
1314my %Typedef_BaseName;
1315my %Typedef_Tr;
1316my %Typedef_Eq;
1317my %StdCxxTypedef;
1318my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001319my %MissedBase;
1320my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001321my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001322
1323# Symbols
1324my %SymbolInfo;
1325my %tr_name;
1326my %mangled_name_gcc;
1327my %mangled_name;
1328my %SkipSymbols = (
1329 "1"=>{},
1330 "2"=>{} );
1331my %SkipNameSpaces = (
1332 "1"=>{},
1333 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001334my %AddNameSpaces = (
1335 "1"=>{},
1336 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001337my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001338my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001339my %SymbolsList_App;
1340my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001341my %Symbol_Library = (
1342 "1"=>{},
1343 "2"=>{} );
1344my %Library_Symbol = (
1345 "1"=>{},
1346 "2"=>{} );
1347my %DepSymbol_Library = (
1348 "1"=>{},
1349 "2"=>{} );
1350my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351 "1"=>{},
1352 "2"=>{} );
1353my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001354my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001356my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001357my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001358my %Library_Needed= (
1359 "1"=>{},
1360 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001361
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001362# Extra Info
1363my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001364my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001365
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001366# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001367my %Include_Preamble = (
1368 "1"=>[],
1369 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001370my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001371my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001372my %HeaderName_Paths;
1373my %Header_Dependency;
1374my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001375my %Include_Paths = (
1376 "1"=>[],
1377 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001378my %INC_PATH_AUTODETECT = (
1379 "1"=>1,
1380 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001381my %Add_Include_Paths = (
1382 "1"=>[],
1383 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my %Skip_Include_Paths;
1385my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001386my %Header_ErrorRedirect;
1387my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001388my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001389my %Header_ShouldNotBeUsed;
1390my %RecursiveIncludes;
1391my %Header_Include_Prefix;
1392my %SkipHeaders;
1393my %SkipHeadersList=(
1394 "1"=>{},
1395 "2"=>{} );
1396my %SkipLibs;
1397my %Include_Order;
1398my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001399my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001400my %TUnit_Funcs;
1401my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001403my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404 "1"=>0,
1405 "2"=>0 );
1406my %AutoPreambleMode = (
1407 "1"=>0,
1408 "2"=>0 );
1409my %MinGWMode = (
1410 "1"=>0,
1411 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001412my %Cpp0xMode = (
1413 "1"=>0,
1414 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001415
1416# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001417my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001418my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001419my %RegisteredSONAMEs;
1420my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001421
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001422my %CheckedArch;
1423
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424# System Objects
1425my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001426my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001427my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428
1429# System Headers
1430my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001431my @DefaultCppPaths;
1432my @DefaultGccPaths;
1433my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434my %DefaultCppHeader;
1435my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001436my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001437
1438# Merging
1439my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001440my $Version;
1441my %AddedInt;
1442my %RemovedInt;
1443my %AddedInt_Virt;
1444my %RemovedInt_Virt;
1445my %VirtualReplacement;
1446my %ChangedTypedef;
1447my %CompatRules;
1448my %IncompleteRules;
1449my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001450my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001451my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452my %ReturnedClass;
1453my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001454my %SourceAlternative;
1455my %SourceAlternative_B;
1456my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001457my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001458
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001459#Report
1460my %TypeChanges;
1461
1462#Speedup
1463my %TypeProblemsIndex;
1464
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001465# Calling Conventions
1466my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001467 1=>{ "R"=>0, "P"=>0 },
1468 2=>{ "R"=>0, "P"=>0 }
1469);
1470
1471# ABI Dump
1472my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001473
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001474# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001475my %TargetLibs;
1476my %TargetHeaders;
1477
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001478# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001479my $OStarget = $OSgroup;
1480my %TargetTools;
1481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001482# Recursion locks
1483my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001484my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001485my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001486my @RecurInclude;
1487my @RecurConstant;
1488
1489# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001490my %SystemPaths = (
1491 "include"=>[],
1492 "lib"=>[],
1493 "bin"=>[]
1494);
1495my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001496my $GCC_PATH;
1497
1498# Symbols versioning
1499my %SymVer = (
1500 "1"=>{},
1501 "2"=>{} );
1502
1503# Problem descriptions
1504my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001505my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506my %TotalAffected;
1507
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001508# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001509my $ContentID = 1;
1510my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001511my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1512my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001513my $ContentSpanEnd = "</span>\n";
1514my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1515my $ContentDivEnd = "</div>\n";
1516my $Content_Counter = 0;
1517
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001518# Modes
1519my $JoinReport = 1;
1520my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001521
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001522my %Severity_Val=(
1523 "High"=>3,
1524 "Medium"=>2,
1525 "Low"=>1,
1526 "Safe"=>-1
1527);
1528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001529sub get_Modules()
1530{
1531 my $TOOL_DIR = get_dirname($0);
1532 if(not $TOOL_DIR)
1533 { # patch for MS Windows
1534 $TOOL_DIR = ".";
1535 }
1536 my @SEARCH_DIRS = (
1537 # tool's directory
1538 abs_path($TOOL_DIR),
1539 # relative path to modules
1540 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001541 # install path
1542 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001543 );
1544 foreach my $DIR (@SEARCH_DIRS)
1545 {
1546 if(not is_abs($DIR))
1547 { # relative path
1548 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1549 }
1550 if(-d $DIR."/modules") {
1551 return $DIR."/modules";
1552 }
1553 }
1554 exitStatus("Module_Error", "can't find modules");
1555}
1556
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001557my %LoadedModules = ();
1558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001559sub loadModule($)
1560{
1561 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001562 if(defined $LoadedModules{$Name}) {
1563 return;
1564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001565 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1566 if(not -f $Path) {
1567 exitStatus("Module_Error", "can't access \'$Path\'");
1568 }
1569 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001570 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001571}
1572
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001573sub readModule($$)
1574{
1575 my ($Module, $Name) = @_;
1576 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1577 if(not -f $Path) {
1578 exitStatus("Module_Error", "can't access \'$Path\'");
1579 }
1580 return readFile($Path);
1581}
1582
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001583sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001584{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001585 my $Number = $_[0];
1586 if(not $Number) {
1587 $Number = 1;
1588 }
1589 else {
1590 $Number = int($Number)+1;
1591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001592 if($Number>3) {
1593 return $Number."th";
1594 }
1595 elsif($Number==1) {
1596 return "1st";
1597 }
1598 elsif($Number==2) {
1599 return "2nd";
1600 }
1601 elsif($Number==3) {
1602 return "3rd";
1603 }
1604 else {
1605 return $Number;
1606 }
1607}
1608
1609sub search_Tools($)
1610{
1611 my $Name = $_[0];
1612 return "" if(not $Name);
1613 if(my @Paths = keys(%TargetTools))
1614 {
1615 foreach my $Path (@Paths)
1616 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001617 if(-f join_P($Path, $Name)) {
1618 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001619 }
1620 if($CrossPrefix)
1621 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001622 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001623 if(-f $Candidate) {
1624 return $Candidate;
1625 }
1626 }
1627 }
1628 }
1629 else {
1630 return "";
1631 }
1632}
1633
1634sub synch_Cmd($)
1635{
1636 my $Name = $_[0];
1637 if(not $GCC_PATH)
1638 { # GCC was not found yet
1639 return "";
1640 }
1641 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001642 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001643 return $Candidate;
1644 }
1645 return "";
1646}
1647
1648sub get_CmdPath($)
1649{
1650 my $Name = $_[0];
1651 return "" if(not $Name);
1652 if(defined $Cache{"get_CmdPath"}{$Name}) {
1653 return $Cache{"get_CmdPath"}{$Name};
1654 }
1655 my %BinUtils = map {$_=>1} (
1656 "c++filt",
1657 "objdump",
1658 "readelf"
1659 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001660 if($BinUtils{$Name} and $GCC_PATH)
1661 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001662 if(my $Dir = get_dirname($GCC_PATH)) {
1663 $TargetTools{$Dir}=1;
1664 }
1665 }
1666 my $Path = search_Tools($Name);
1667 if(not $Path and $OSgroup eq "windows") {
1668 $Path = search_Tools($Name.".exe");
1669 }
1670 if(not $Path and $BinUtils{$Name})
1671 {
1672 if($CrossPrefix)
1673 { # user-defined prefix
1674 $Path = search_Cmd($CrossPrefix."-".$Name);
1675 }
1676 }
1677 if(not $Path and $BinUtils{$Name})
1678 {
1679 if(my $Candidate = synch_Cmd($Name))
1680 { # synch with GCC
1681 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001682 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001683 if(-f $Candidate) {
1684 $Path = $Candidate;
1685 }
1686 }
1687 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001688 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001689 $Path = $Candidate;
1690 }
1691 }
1692 }
1693 if(not $Path) {
1694 $Path = search_Cmd($Name);
1695 }
1696 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001697 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001698 $Path=search_Cmd($Name.".exe");
1699 }
1700 if($Path=~/\s/) {
1701 $Path = "\"".$Path."\"";
1702 }
1703 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1704}
1705
1706sub search_Cmd($)
1707{
1708 my $Name = $_[0];
1709 return "" if(not $Name);
1710 if(defined $Cache{"search_Cmd"}{$Name}) {
1711 return $Cache{"search_Cmd"}{$Name};
1712 }
1713 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1714 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1715 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001716 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001717 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001718 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001719 if(-f $CmdPath)
1720 {
1721 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001722 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001723 }
1724 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1725 }
1726 }
1727 return ($Cache{"search_Cmd"}{$Name} = "");
1728}
1729
1730sub get_CmdPath_Default($)
1731{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001732 return "" if(not $_[0]);
1733 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1734 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001735 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1737}
1738
1739sub get_CmdPath_Default_I($)
1740{ # search in PATH
1741 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001742 if($Name=~/find/)
1743 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001744 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001745 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 }
1747 }
1748 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001749 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001750 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001751 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001752 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001754 if($OSgroup eq "windows")
1755 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001756 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001757 return $Name;
1758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001759 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001760 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001761 {
1762 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001763 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001764 }
1765 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001766 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767}
1768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001769sub classifyPath($)
1770{
1771 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001772 if($Path=~/[\*\+\(\[\|]/)
1773 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001774 return ($Path, "Pattern");
1775 }
1776 elsif($Path=~/[\/\\]/)
1777 { # directory or relative path
1778 return (path_format($Path, $OSgroup), "Path");
1779 }
1780 else {
1781 return ($Path, "Name");
1782 }
1783}
1784
1785sub readDescriptor($$)
1786{
1787 my ($LibVersion, $Content) = @_;
1788 return if(not $LibVersion);
1789 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1790 if(not $Content) {
1791 exitStatus("Error", "$DName is empty");
1792 }
1793 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001794 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001795 }
1796 $Content=~s/\/\*(.|\n)+?\*\///g;
1797 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001798
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001799 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1800 if($TargetVersion{$LibVersion}) {
1801 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1802 }
1803 if(not $Descriptor{$LibVersion}{"Version"}) {
1804 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1805 }
1806 if($Content=~/{RELPATH}/)
1807 {
1808 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1809 $Content =~ s/{RELPATH}/$RelDir/g;
1810 }
1811 else
1812 {
1813 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1814 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1815 }
1816 }
1817
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001818 my $DHeaders = parseTag(\$Content, "headers");
1819 if(not $DHeaders) {
1820 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1821 }
1822 elsif(lc($DHeaders) ne "none")
1823 { # append the descriptor headers list
1824 if($Descriptor{$LibVersion}{"Headers"})
1825 { # multiple descriptors
1826 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001827 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001828 else {
1829 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1830 }
1831 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1832 {
1833 if(not -e $Path) {
1834 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835 }
1836 }
1837 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001838
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001839 if(not $CheckHeadersOnly_Opt)
1840 {
1841 my $DObjects = parseTag(\$Content, "libs");
1842 if(not $DObjects) {
1843 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1844 }
1845 elsif(lc($DObjects) ne "none")
1846 { # append the descriptor libraries list
1847 if($Descriptor{$LibVersion}{"Libs"})
1848 { # multiple descriptors
1849 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1850 }
1851 else {
1852 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1853 }
1854 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1855 {
1856 if(not -e $Path) {
1857 exitStatus("Access_Error", "can't access \'$Path\'");
1858 }
1859 }
1860 }
1861 }
1862 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1863 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 if(not -d $Path) {
1865 exitStatus("Access_Error", "can't access directory \'$Path\'");
1866 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001867 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001868 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001869 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001870 }
1871 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1872 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001873 if(not -d $Path) {
1874 exitStatus("Access_Error", "can't access directory \'$Path\'");
1875 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001876 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001878 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 }
1880 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1881 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001882 if(not -d $Path) {
1883 exitStatus("Access_Error", "can't access directory \'$Path\'");
1884 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001885 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001886 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001887 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001888 $TargetTools{$Path}=1;
1889 }
1890 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1891 $CrossPrefix = $Prefix;
1892 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001893 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1895 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896 if(not -d $Path) {
1897 exitStatus("Access_Error", "can't access directory \'$Path\'");
1898 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001899 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001900 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001901 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001902 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001903 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001904 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1905 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 if(not -d $Path) {
1907 exitStatus("Access_Error", "can't access directory \'$Path\'");
1908 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001909 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001910 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001911 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001912 }
1913 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001914 { # skip some auto-generated include paths
1915 if(not is_abs($Path))
1916 {
1917 if(my $P = abs_path($Path)) {
1918 $Path = $P;
1919 }
1920 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001921 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 }
1923 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001924 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001925 my ($CPath, $Type) = classifyPath($Path);
1926 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001927 }
1928 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001929 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1930 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001931 if($Option!~/\A\-(Wl|l|L)/)
1932 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001933 $CompilerOptions{$LibVersion} .= " ".$Option;
1934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001935 }
1936 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1937 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1938 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001939 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001940
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001941 my ($CPath, $Type) = classifyPath($Path);
1942 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001943 }
1944 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1945 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1946 {
1947 my ($CPath, $Type) = classifyPath($Path);
1948 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1949 }
1950 if(my $DDefines = parseTag(\$Content, "defines"))
1951 {
1952 if($Descriptor{$LibVersion}{"Defines"})
1953 { # multiple descriptors
1954 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1955 }
1956 else {
1957 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1958 }
1959 }
1960 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1961 {
1962 if($Order=~/\A(.+):(.+)\Z/) {
1963 $Include_Order{$LibVersion}{$1} = $2;
1964 }
1965 }
1966 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1967 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001968 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001969 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1970 }
1971 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1972 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001973 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001974 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1975 }
1976 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1977 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1978 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001979 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1980 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001982 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1983 $SkipConstants{$LibVersion}{$Constant} = 1;
1984 }
1985 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1986 {
1987 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001988 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001989 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1990 }
1991 else {
1992 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1993 }
1994 }
1995}
1996
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001997sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001998{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001999 my $CodeRef = shift(@_);
2000 my $Tag = shift(@_);
2001 if(not $Tag or not $CodeRef) {
2002 return undef;
2003 }
2004 my $Sp = 0;
2005 if(@_) {
2006 $Sp = shift(@_);
2007 }
2008 my $Start = index(${$CodeRef}, "<$Tag>");
2009 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002010 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002011 my $End = index(${$CodeRef}, "</$Tag>");
2012 if($End!=-1)
2013 {
2014 my $TS = length($Tag)+3;
2015 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2016 substr($Content, 0, $TS-1, ""); # cut start tag
2017 substr($Content, -$TS, $TS, ""); # cut end tag
2018 if(not $Sp)
2019 {
2020 $Content=~s/\A\s+//g;
2021 $Content=~s/\s+\Z//g;
2022 }
2023 if(substr($Content, 0, 1) ne "<") {
2024 $Content = xmlSpecChars_R($Content);
2025 }
2026 return $Content;
2027 }
2028 }
2029 return undef;
2030}
2031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002032sub getInfo($)
2033{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002034 my $DumpPath = $_[0];
2035 return if(not $DumpPath or not -f $DumpPath);
2036
2037 readTUDump($DumpPath);
2038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 # processing info
2040 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002041
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002042 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002043 setAnonTypedef_All();
2044 }
2045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002046 getTypeInfo_All();
2047 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002048 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002049 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002050 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002051
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002052 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002053 %LibInfo = ();
2054 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002055 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002056 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002057 %TemplateDecl = ();
2058 %StdCxxTypedef = ();
2059 %MissedTypedef = ();
2060 %Typedef_Tr = ();
2061 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002062 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002063
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002064 # clean cache
2065 delete($Cache{"getTypeAttr"});
2066 delete($Cache{"getTypeDeclId"});
2067
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002068 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002069 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002070 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002071 }
2072 else
2073 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002074 if($BinaryOnly and not $ExtendedCheck)
2075 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002076 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002077 }
2078 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002079 remove_Unused($Version, "Extended");
2080 }
2081 }
2082
2083 if($CheckInfo)
2084 {
2085 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2086 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2087 }
2088
2089 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2090 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002092 }
2093
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002094 if($Debug) {
2095 # debugMangling($Version);
2096 }
2097}
2098
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002099sub readTUDump($)
2100{
2101 my $DumpPath = $_[0];
2102
2103 open(TU_DUMP, $DumpPath);
2104 local $/ = undef;
2105 my $Content = <TU_DUMP>;
2106 close(TU_DUMP);
2107
2108 unlink($DumpPath);
2109
2110 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002111 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002112
2113 # clean memory
2114 undef $Content;
2115
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002116 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002117
2118 foreach (0 .. $#Lines)
2119 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002120 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002121 { # get a number and attributes of a node
2122 next if(not $NodeType{$2});
2123 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002124 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002125 }
2126
2127 # clean memory
2128 delete($Lines[$_]);
2129 }
2130
2131 # clean memory
2132 undef @Lines;
2133}
2134
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002135sub simplifyConstants()
2136{
2137 foreach my $Constant (keys(%{$Constants{$Version}}))
2138 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002139 if(defined $Constants{$Version}{$Constant}{"Header"})
2140 {
2141 my $Value = $Constants{$Version}{$Constant}{"Value"};
2142 if(defined $EnumConstants{$Version}{$Value}) {
2143 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2144 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002145 }
2146 }
2147}
2148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002149sub simplifyNames()
2150{
2151 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2152 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002153 if($Typedef_Eq{$Version}{$Base}) {
2154 next;
2155 }
2156 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2157 if($#Translations==0)
2158 {
2159 if(length($Translations[0])<=length($Base)) {
2160 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2161 }
2162 }
2163 else
2164 { # select most appropriate
2165 foreach my $Tr (@Translations)
2166 {
2167 if($Base=~/\A\Q$Tr\E/)
2168 {
2169 $Typedef_Eq{$Version}{$Base} = $Tr;
2170 last;
2171 }
2172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002173 }
2174 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002175 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002176 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002177 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002178 if(not $TypeName) {
2179 next;
2180 }
2181 next if(index($TypeName,"<")==-1);# template instances only
2182 if($TypeName=~/>(::\w+)+\Z/)
2183 { # skip unused types
2184 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002185 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002186 foreach my $Base (sort {length($b)<=>length($a)}
2187 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002188 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002189 next if(not $Base);
2190 next if(index($TypeName,$Base)==-1);
2191 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002192 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002193 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002194 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2195 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2196 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002197 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002198 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2199 {
2200 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2201 {
2202 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2203 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002204 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002205 }
2206 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002210 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002211 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2212 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002213 }
2214}
2215
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002216sub setAnonTypedef_All()
2217{
2218 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2219 {
2220 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2221 {
2222 if(isAnon(getNameByInfo($InfoId))) {
2223 $TypedefToAnon{getTypeId($InfoId)} = 1;
2224 }
2225 }
2226 }
2227}
2228
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002229sub setTemplateParams_All()
2230{
2231 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2232 {
2233 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2234 setTemplateParams($_);
2235 }
2236 }
2237}
2238
2239sub setTemplateParams($)
2240{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002241 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002242 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002243 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002244 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002245 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002246 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002247 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002248 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002249 setTemplateInstParams($_[0], $TmplInst_Id);
2250 }
2251 }
2252
2253 $BasicTemplate{$Version}{$Tid} = $_[0];
2254
2255 if(my $Prms = getTreeAttr_Prms($_[0]))
2256 {
2257 if(my $Valu = getTreeAttr_Valu($Prms))
2258 {
2259 my $Vector = getTreeVec($Valu);
2260 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2261 {
2262 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2263 {
2264 if(my $Name = getNameByInfo($Val))
2265 {
2266 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2267 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2268 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2269 }
2270 else {
2271 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2272 }
2273 }
2274 }
2275 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002277 }
2278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002279 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002280 {
2281 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2282 {
2283 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002284 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002285 }
2286 }
2287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002288}
2289
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002290sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002291{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002292 my ($Tmpl, $Inst) = @_;
2293
2294 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002296 my ($Params_InfoId, $ElemId) = ();
2297 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2298 $Params_InfoId = $1;
2299 }
2300 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2301 $ElemId = $1;
2302 }
2303 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002304 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002305 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2306 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2307 {
2308 my ($PPos, $PTypeId) = ($1, $2);
2309 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2310 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002311 if($PType eq "template_type_parm") {
2312 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002313 }
2314 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002315 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2316 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002317 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002318 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002319 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002320 else
2321 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002322 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002323 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002325 }
2326 }
2327 }
2328}
2329
2330sub getTypeDeclId($)
2331{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002332 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002333 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002334 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2335 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2336 }
2337 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2338 {
2339 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2340 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2341 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002344 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345}
2346
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002347sub getTypeInfo_All()
2348{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002349 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002350 { # support for GCC < 4.5
2351 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2352 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2353 # FIXME: check GCC versions
2354 addMissedTypes_Pre();
2355 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002357 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002358 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002359 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2360 if($IType=~/_type\Z/ and $IType ne "function_type"
2361 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002362 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363 }
2364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002365
2366 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002367 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002368 "Name" => "...",
2369 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002370 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002371 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002372 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002373
2374 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 { # support for GCC < 4.5
2376 addMissedTypes_Post();
2377 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002378
2379 if($ADD_TMPL_INSTANCES)
2380 {
2381 # templates
2382 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2383 {
2384 if(defined $TemplateMap{$Version}{$Tid}
2385 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2386 {
2387 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2388 {
2389 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2390 {
2391 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2392 {
2393 if(my %MAttr = getTypeAttr($MembTypeId))
2394 {
2395 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2396 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2397 }
2398 }
2399 }
2400 }
2401 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2402 {
2403 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2404 {
2405 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2406
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002407 if($NBid ne $Bid
2408 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002409 {
2410 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2411 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2412 }
2413 }
2414 }
2415 }
2416 }
2417 }
2418}
2419
2420sub createType($$)
2421{
2422 my ($Attr, $LibVersion) = @_;
2423 my $NewId = ++$MAX_ID;
2424
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002425 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002426 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002427 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002428
2429 return "$NewId";
2430}
2431
2432sub instType($$$)
2433{ # create template instances
2434 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002435
2436 if(not $TypeInfo{$LibVersion}{$Tid}) {
2437 return undef;
2438 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002439 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2440
2441 foreach my $Key (sort keys(%{$Map}))
2442 {
2443 if(my $Val = $Map->{$Key})
2444 {
2445 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2446
2447 if(defined $Attr->{"NameSpace"}) {
2448 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2449 }
2450 foreach (keys(%{$Attr->{"TParam"}})) {
2451 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2452 }
2453 }
2454 else
2455 { # remove absent
2456 # _Traits, etc.
2457 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002458 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002459 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2460 }
2461 foreach (keys(%{$Attr->{"TParam"}}))
2462 {
2463 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2464 delete($Attr->{"TParam"}{$_});
2465 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002466 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002467 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2468 }
2469 }
2470 }
2471 }
2472
2473 my $Tmpl = 0;
2474
2475 if(defined $Attr->{"TParam"})
2476 {
2477 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2478 {
2479 my $PName = $Attr->{"TParam"}{$_}{"name"};
2480
2481 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2482 {
2483 my %Base = get_BaseType($PTid, $LibVersion);
2484
2485 if($Base{"Type"} eq "TemplateParam"
2486 or defined $Base{"Template"})
2487 {
2488 $Tmpl = 1;
2489 last
2490 }
2491 }
2492 }
2493 }
2494
2495 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2496 return "$Id";
2497 }
2498 else
2499 {
2500 if(not $Tmpl) {
2501 delete($Attr->{"Template"});
2502 }
2503
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002504 my $New = createType($Attr, $LibVersion);
2505
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002506 my %EMap = ();
2507 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2508 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2509 }
2510 foreach (keys(%{$Map})) {
2511 $EMap{$_} = $Map->{$_};
2512 }
2513
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002514 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2515 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002516 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002517 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002518 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002519 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002520 {
2521 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2522
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002523 if($NBid ne $Bid
2524 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002525 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002526 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2527 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002528 }
2529 }
2530 }
2531
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002532 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002533 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002534 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2535 {
2536 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2537 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2538 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002539 }
2540 }
2541
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002542 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002543 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002544 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2545 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002546 }
2547 }
2548
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002549 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2550 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002551 }
2552
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002553 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002555}
2556
2557sub addMissedTypes_Pre()
2558{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002559 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002560 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2561 { # detecting missed typedefs
2562 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2563 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002564 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002565 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002566 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002567 if($TypeType eq "Unknown")
2568 { # template_type_parm
2569 next;
2570 }
2571 my $TypeDeclId = getTypeDeclId($TypeId);
2572 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2573 my $TypedefName = getNameByInfo($MissedTDid);
2574 next if(not $TypedefName);
2575 next if($TypedefName eq "__float80");
2576 next if(isAnon($TypedefName));
2577 if(not $TypeDeclId
2578 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002579 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002580 }
2581 }
2582 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002583 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002584 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002585 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002586 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002587 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588 next;
2589 }
2590 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002591 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002592 if(not $TypedefName) {
2593 next;
2594 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002595 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 my %MissedInfo = ( # typedef info
2597 "Name" => $TypedefName,
2598 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002599 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002601 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 my ($H, $L) = getLocation($MissedTDid);
2603 $MissedInfo{"Header"} = $H;
2604 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002605 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 { # other types
2607 next;
2608 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002609 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 next;
2612 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002613 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002615 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002617 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002619 next;
2620 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002621 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 next;
2623 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002624 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002625 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 next;
2627 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002628 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 next;
2631 }
2632 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633
2634 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002636 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002638 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002639 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002640 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002641
2642 # add missed & remove other
2643 $TypeInfo{$Version} = \%AddTypes;
2644 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002645}
2646
2647sub addMissedTypes_Post()
2648{
2649 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2650 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002651 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2652 {
2653 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2654 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2655 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2656 }
2657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658 }
2659}
2660
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002661sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002663 my $TypeId = $_[0];
2664 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2665 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002667 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669}
2670
2671sub getArraySize($$)
2672{
2673 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002674 if(my $Size = getSize($TypeId))
2675 {
2676 my $Elems = $Size/$BYTE_SIZE;
2677 while($BaseName=~s/\s*\[(\d+)\]//) {
2678 $Elems/=$1;
2679 }
2680 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2681 {
2682 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2683 $Elems/=$BasicSize;
2684 }
2685 }
2686 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002689}
2690
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002691sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002692{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002693 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002694 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002695 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2696 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002697 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002698 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2699 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2700 if(not $NodeType)
2701 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002702 return ();
2703 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002704 if($NodeType eq "tree_vec")
2705 {
2706 if($Pos!=$#Positions)
2707 { # select last vector of parameters ( ns<P1>::type<P2> )
2708 next;
2709 }
2710 }
2711 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2712 foreach my $P (@Params)
2713 {
2714 if($P eq "") {
2715 return ();
2716 }
2717 elsif($P ne "\@skip\@") {
2718 @TmplParams = (@TmplParams, $P);
2719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720 }
2721 }
2722 return @TmplParams;
2723}
2724
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002725sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002726{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002727 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002728 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002729 if(defined $TypeInfo{$Version}{$TypeId}
2730 and $TypeInfo{$Version}{$TypeId}{"Name"})
2731 { # already created
2732 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002733 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002734 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2735 { # incomplete type
2736 return ();
2737 }
2738 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2739
2740 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002741 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002742
2743 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2744 {
2745 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2746 {
2747 if($Info=~/qual[ ]*:/)
2748 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002749 my $NewId = ++$MAX_ID;
2750
2751 $MissedBase{$Version}{$TypeId} = "$NewId";
2752 $MissedBase_R{$Version}{$NewId} = $TypeId;
2753 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2754 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002755 }
2756 }
2757 $TypeAttr{"Type"} = "Typedef";
2758 }
2759 else {
2760 $TypeAttr{"Type"} = getTypeType($TypeId);
2761 }
2762
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002763 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2764 {
2765 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2766 { # local code
2767 return ();
2768 }
2769 }
2770
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002771 if($TypeAttr{"Type"} eq "Unknown") {
2772 return ();
2773 }
2774 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2775 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002776 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002777 if(my $TName = $TypeAttr{"Name"})
2778 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002779 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002780 $TName_Tid{$Version}{$TName} = $TypeId;
2781 return %TypeAttr;
2782 }
2783 else {
2784 return ();
2785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002786 }
2787 elsif($TypeAttr{"Type"} eq "Array")
2788 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002789 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2790 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002791 return ();
2792 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002793 if(my $Algn = getAlgn($TypeId)) {
2794 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2795 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002796 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002797 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002798 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002799 if(not $BTAttr{"Name"}) {
2800 return ();
2801 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002802 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002803 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002804 if(my $Size = getSize($TypeId)) {
2805 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2806 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002807 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2809 }
2810 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002811 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002813 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002814 else
2815 {
2816 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002817 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002818 $TypeAttr{"Name"} = $1."[]".$2;
2819 }
2820 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002823 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002824 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002825 if($BTAttr{"Header"}) {
2826 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002827 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002828 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002829 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2830 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002831 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002832 return ();
2833 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002834 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002835 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002836 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002837 if($TypeAttr{"Name"})
2838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002839 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002840
2841 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2842 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002843 { # NOTE: register only one int: with built-in decl
2844 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2845 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2846 }
2847 }
2848 return %TypeAttr;
2849 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002850 else {
2851 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002853 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002854 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2855 {
2856 %TypeAttr = getTrivialTypeAttr($TypeId);
2857 if($TypeAttr{"Name"})
2858 {
2859 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2860 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2861 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2862 }
2863 return %TypeAttr;
2864 }
2865 else {
2866 return ();
2867 }
2868 }
2869 elsif($TypeAttr{"Type"} eq "SizeOf")
2870 {
2871 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2872 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2873 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2874 if($TypeAttr{"Name"})
2875 {
2876 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2877 return %TypeAttr;
2878 }
2879 else {
2880 return ();
2881 }
2882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002884 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002885 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2886 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002887 return ();
2888 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002889 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002890 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002891 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002892 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002893 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002894 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002895 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002897 }
2898 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002899 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002900 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002901 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 return ();
2903 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002904 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002905 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002906 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002907 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002908 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 }
2910 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002911 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002912 {
2913 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002914 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002915 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002916 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002917 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2918 }
2919 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002920 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 }
2922 }
2923 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002924 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002925 }
2926 if($TypeAttr{"Type"} eq "Typedef")
2927 {
2928 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002929
2930 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2931 return ();
2932 }
2933
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002934 if(isAnon($TypeAttr{"Name"}))
2935 { # anon typedef to anon type: ._N
2936 return ();
2937 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002938
2939 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2940 { # artificial typedef of "struct X" to "X"
2941 $TypeAttr{"Artificial"} = 1;
2942 }
2943
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002944 if(my $NS = getNameSpace($TypeDeclId))
2945 {
2946 my $TypeName = $TypeAttr{"Name"};
2947 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2948 { # "some_type" is the typedef to "struct some_type" in C++
2949 if($3) {
2950 $TypeAttr{"Name"} = $3."::".$TypeName;
2951 }
2952 }
2953 else
2954 {
2955 $TypeAttr{"NameSpace"} = $NS;
2956 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002957
2958 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2959 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2960 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002961 if($BTAttr{"NameSpace"}
2962 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002963 { # types like "std::fpos<__mbstate_t>" are
2964 # not covered by typedefs in the TU dump
2965 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002966 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2967 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002968 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002969 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002970 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002971 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002973 }
2974 }
2975 }
2976 }
2977 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002978 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002979 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002980 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002981 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2982 { # typedef int*const TYPEDEF; // first
2983 # int foo(TYPEDEF p); // const is optimized out
2984 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2985 if($BTAttr{"Name"}=~/</)
2986 {
2987 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2988 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002990 }
2991 }
2992 }
2993 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2994 }
2995 if(not $TypeAttr{"Size"})
2996 {
2997 if($TypeAttr{"Type"} eq "Pointer") {
2998 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2999 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003000 elsif($BTAttr{"Size"}) {
3001 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003002 }
3003 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003004 if(my $Algn = getAlgn($TypeId)) {
3005 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3006 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003007 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003008 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3009 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003010 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003011 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003012 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003013 { # typedef to "class Class"
3014 # should not be registered in TName_Tid
3015 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3016 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003018 }
3019 return %TypeAttr;
3020 }
3021}
3022
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003023sub getTreeVec($)
3024{
3025 my %Vector = ();
3026 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3027 {
3028 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3029 { # string length is N-1 because of the null terminator
3030 $Vector{$1} = $2;
3031 }
3032 }
3033 return \%Vector;
3034}
3035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003036sub get_TemplateParam($$)
3037{
3038 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003039 return () if(not $Type_Id);
3040 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3041 return () if(not $NodeType);
3042 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003043 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003044 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003045 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 my $Num = getNodeIntCst($Type_Id);
3047 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003048 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003049 }
3050 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003051 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003052 }
3053 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003054 elsif($NodeType eq "string_cst") {
3055 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003056 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003057 elsif($NodeType eq "tree_vec")
3058 {
3059 my $Vector = getTreeVec($Type_Id);
3060 my @Params = ();
3061 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3062 {
3063 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3064 push(@Params, $P2);
3065 }
3066 }
3067 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003068 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003069 elsif($NodeType eq "parm_decl")
3070 {
3071 (getNameByInfo($Type_Id));
3072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003073 else
3074 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003075 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003076 my $PName = $ParamAttr{"Name"};
3077 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003078 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003080 if($PName=~/\>/)
3081 {
3082 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003083 $PName = $Cover;
3084 }
3085 }
3086 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003087 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003088 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3089 # template<typename _Key, typename _Compare = std::less<_Key>
3090 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3091 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3092 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3093 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003094 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003096 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 }
3098}
3099
3100sub cover_stdcxx_typedef($)
3101{
3102 my $TypeName = $_[0];
3103 if(my @Covers = sort {length($a)<=>length($b)}
3104 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3105 { # take the shortest typedef
3106 # FIXME: there may be more than
3107 # one typedefs to the same type
3108 return $Covers[0];
3109 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003110 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3112 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3113 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003114 if(my $Cover = $Covers[0])
3115 {
3116 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3117 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3118 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003120 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003121}
3122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123sub getNodeIntCst($)
3124{
3125 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003126 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127 if($EnumMembName_Id{$Version}{$CstId}) {
3128 return $EnumMembName_Id{$Version}{$CstId};
3129 }
3130 elsif((my $Value = getTreeValue($CstId)) ne "")
3131 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003132 if($Value eq "0")
3133 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003134 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003135 return "false";
3136 }
3137 else {
3138 return "0";
3139 }
3140 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003141 elsif($Value eq "1")
3142 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003143 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003144 return "true";
3145 }
3146 else {
3147 return "1";
3148 }
3149 }
3150 else {
3151 return $Value;
3152 }
3153 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003154 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003155}
3156
3157sub getNodeStrCst($)
3158{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003159 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3160 {
3161 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003162 {
3163 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3164 { # string length is N-1 because of the null terminator
3165 return substr($1, 0, $2-1);
3166 }
3167 else
3168 { # identifier_node
3169 return substr($1, 0, $2);
3170 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003171 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003172 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003173 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003174}
3175
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003177{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003178 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003179 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3180 if($Type eq "FieldPtr") {
3181 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3182 }
3183 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3184 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003185 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003186 if($Type eq "MethodPtr")
3187 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003188 if(my $Size = getSize($TypeId))
3189 {
3190 $Size/=$BYTE_SIZE;
3191 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003194 if(my $Algn = getAlgn($TypeId)) {
3195 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003197 # Return
3198 if($Type eq "FieldPtr")
3199 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003200 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003201 if($ReturnAttr{"Name"}) {
3202 $MemPtrName .= $ReturnAttr{"Name"};
3203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003204 $TypeAttr{"Return"} = $PtrId;
3205 }
3206 else
3207 {
3208 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3209 {
3210 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003211 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3212 if(not $ReturnAttr{"Name"})
3213 { # templates
3214 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 $TypeAttr{"Return"} = $ReturnTypeId;
3218 }
3219 }
3220 # Class
3221 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3222 {
3223 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003224 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003225 if($Class{"Name"}) {
3226 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3227 }
3228 else {
3229 $MemPtrName .= " (*)";
3230 }
3231 }
3232 else {
3233 $MemPtrName .= " (*)";
3234 }
3235 # Parameters
3236 if($Type eq "FuncPtr"
3237 or $Type eq "MethodPtr")
3238 {
3239 my @ParamTypeName = ();
3240 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3241 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003242 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003243 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003244 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003245 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003246 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3247 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003248 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003249 my $PTypeId = $1;
3250 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 if(not $ParamAttr{"Name"})
3252 { # templates (template_type_parm), etc.
3253 return ();
3254 }
3255 if($ParamAttr{"Name"} eq "void") {
3256 last;
3257 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003258 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003259 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003260 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003261 push(@ParamTypeName, $ParamAttr{"Name"});
3262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003263 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3264 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 }
3266 else {
3267 last;
3268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003269 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003270 else {
3271 last;
3272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003273 }
3274 }
3275 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3276 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003277 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003278 return %TypeAttr;
3279}
3280
3281sub getTreeTypeName($)
3282{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003283 my $TypeId = $_[0];
3284 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003286 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003287 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003288 if(my $Name = getNameByInfo($TypeId))
3289 { # bit_size_type
3290 return $Name;
3291 }
3292 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003293 return "unsigned int";
3294 }
3295 else {
3296 return "int";
3297 }
3298 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003299 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300 return getNameByInfo($1);
3301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003302 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003303 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003304}
3305
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003306sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003308 my $Ptd = pointTo($_[0]);
3309 return 0 if(not $Ptd);
3310 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003311 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003312 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3313 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003314 }
3315 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003316 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3317 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003319 if($InfoT1 eq "pointer_type"
3320 and $InfoT2 eq "function_type") {
3321 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003322 }
3323 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003324 return 0;
3325}
3326
3327sub isMethodPtr($)
3328{
3329 my $Ptd = pointTo($_[0]);
3330 return 0 if(not $Ptd);
3331 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3332 {
3333 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3334 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3335 and $Info=~/ ptrmem /) {
3336 return 1;
3337 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003338 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003339 return 0;
3340}
3341
3342sub isFieldPtr($)
3343{
3344 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3345 {
3346 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3347 and $Info=~/ ptrmem /) {
3348 return 1;
3349 }
3350 }
3351 return 0;
3352}
3353
3354sub pointTo($)
3355{
3356 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3357 {
3358 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3359 return $1;
3360 }
3361 }
3362 return "";
3363}
3364
3365sub getTypeTypeByTypeId($)
3366{
3367 my $TypeId = $_[0];
3368 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3369 {
3370 my $NType = $NodeType{$TType};
3371 if($NType eq "Intrinsic") {
3372 return $NType;
3373 }
3374 elsif(isFuncPtr($TypeId)) {
3375 return "FuncPtr";
3376 }
3377 elsif(isMethodPtr($TypeId)) {
3378 return "MethodPtr";
3379 }
3380 elsif(isFieldPtr($TypeId)) {
3381 return "FieldPtr";
3382 }
3383 elsif($NType ne "Other") {
3384 return $NType;
3385 }
3386 }
3387 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003388}
3389
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003390my %UnQual = (
3391 "r"=>"restrict",
3392 "v"=>"volatile",
3393 "c"=>"const",
3394 "cv"=>"const volatile"
3395);
3396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003397sub getQual($)
3398{
3399 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003400 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3401 {
3402 my ($Qual, $To) = ();
3403 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3404 $Qual = $UnQual{$1};
3405 }
3406 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3407 $To = $1;
3408 }
3409 if($Qual and $To) {
3410 return ($Qual, $To);
3411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003412 }
3413 return ();
3414}
3415
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003416sub getQualType($)
3417{
3418 if($_[0] eq "const volatile") {
3419 return "ConstVolatile";
3420 }
3421 return ucfirst($_[0]);
3422}
3423
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003424sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003425{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003426 my $TypeId = $_[0];
3427 my $TypeDeclId = getTypeDeclId($TypeId);
3428 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003429 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003430 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3431 return "Typedef";
3432 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003433 }
3434 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3435 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003436 if(($Qual or $To) and $TypeDeclId
3437 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003438 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003439 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003440 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003441 elsif(not $MissedBase_R{$Version}{$TypeId}
3442 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003443 return "Typedef";
3444 }
3445 elsif($Qual)
3446 { # qualified types
3447 return getQualType($Qual);
3448 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003449
3450 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3451 { # typedef struct { ... } name
3452 $TypeTypedef{$Version}{$TypeId} = $1;
3453 }
3454
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003455 my $TypeType = getTypeTypeByTypeId($TypeId);
3456 if($TypeType eq "Struct")
3457 {
3458 if($TypeDeclId
3459 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3460 return "Template";
3461 }
3462 }
3463 return $TypeType;
3464}
3465
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003466sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003467{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003468 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003469 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003470 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3471 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3472 return 0;
3473 }
3474 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3475 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003476 if(my $TDid = getTypeDeclId($_[0]))
3477 {
3478 if(getTypeId($TDid) eq $_[0]
3479 and getNameByInfo($TDid))
3480 {
3481 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3482 return $1;
3483 }
3484 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003485 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003486 }
3487 }
3488 return 0;
3489}
3490
3491sub selectBaseType($)
3492{
3493 my $TypeId = $_[0];
3494 if(defined $MissedTypedef{$Version}{$TypeId})
3495 { # add missed typedefs
3496 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3497 return ($TypeId, "");
3498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003499 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003500 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3501 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003502
3503 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3504 my $MB = $MissedBase{$Version}{$TypeId};
3505
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003506 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003507 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003508 and (getTypeId($1) ne $TypeId)
3509 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003510 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003511 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003512 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003513 elsif($MB)
3514 { # add base
3515 return ($MB, "");
3516 }
3517 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003518 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003519 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 elsif($Qual or $To)
3522 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003523 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003524 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003525 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003527 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003528 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003530 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003531 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003533 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003534 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003536 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003537 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003538 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003539 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003540 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003542 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003543
3544 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545}
3546
3547sub getSymbolInfo_All()
3548{
3549 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3550 { # reverse order
3551 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003553 }
3554 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003555
3556 if($ADD_TMPL_INSTANCES)
3557 {
3558 # templates
3559 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3560 {
3561 my %Map = ();
3562
3563 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3564 {
3565 if(defined $TemplateMap{$Version}{$ClassId})
3566 {
3567 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3568 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3569 }
3570 }
3571 }
3572
3573 if(defined $TemplateMap{$Version}{$Sid})
3574 {
3575 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3576 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3577 }
3578 }
3579
3580 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3581 {
3582 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3583 {
3584 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3585 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3586 }
3587 }
3588 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3589 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3590 }
3591 }
3592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003593}
3594
3595sub getVarInfo_All()
3596{
3597 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3598 { # reverse order
3599 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003600 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003601 }
3602 }
3603}
3604
3605sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003606 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003607}
3608
3609sub getVarInfo($)
3610{
3611 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003612 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003613 {
3614 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3615 if($NSInfoType and $NSInfoType eq "function_decl") {
3616 return;
3617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003618 }
3619 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3620 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3621 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3622 delete($SymbolInfo{$Version}{$InfoId});
3623 return;
3624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003625 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003626 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003627 delete($SymbolInfo{$Version}{$InfoId});
3628 return;
3629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003630 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3631 delete($SymbolInfo{$Version}{$InfoId});
3632 return;
3633 }
3634 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003635 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3636 {
3637 if($OSgroup eq "windows")
3638 { # cut the offset
3639 $MnglName=~s/\@\d+\Z//g;
3640 }
3641 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003643 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003644 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003645 { # validate mangled name
3646 delete($SymbolInfo{$Version}{$InfoId});
3647 return;
3648 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003650 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003651 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003652 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 }
3654 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3655 { # non-public global data
3656 delete($SymbolInfo{$Version}{$InfoId});
3657 return;
3658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003659 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003660 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003661 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003662 if(not defined $TypeInfo{$Version}{$Rid}
3663 or not $TypeInfo{$Version}{$Rid}{"Name"})
3664 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003665 delete($SymbolInfo{$Version}{$InfoId});
3666 return;
3667 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003668 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3669 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003670 if(defined $Val) {
3671 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
3674 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003675 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3676 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003677 if(not defined $TypeInfo{$Version}{$ClassId}
3678 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3679 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003680 delete($SymbolInfo{$Version}{$InfoId});
3681 return;
3682 }
3683 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003684 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3685 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003686 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003687 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003689 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003690 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003691 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003692 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003693 if(not $CheckHeadersOnly)
3694 {
3695 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3696 {
3697 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3698 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3699 {
3700 if(link_symbol($ShortName, $Version, "-Deps"))
3701 { # "const" global data is mangled as _ZL... in the TU dump
3702 # but not mangled when compiling a C shared library
3703 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3704 }
3705 }
3706 }
3707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003708 if($COMMON_LANGUAGE{$Version} eq "C++")
3709 {
3710 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3711 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003712 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003713 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3714 }
3715 }
3716 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3717 { # try to mangle symbol (link with libraries)
3718 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3719 }
3720 if($OStarget eq "windows")
3721 {
3722 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3723 { # link MS C++ symbols from library with GCC symbols from headers
3724 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3725 }
3726 }
3727 }
3728 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3729 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3730 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003731 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3732 {
3733 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3734 { # non-target symbols
3735 delete($SymbolInfo{$Version}{$InfoId});
3736 return;
3737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003738 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003739 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3740 {
3741 if(defined $MissedTypedef{$Version}{$Rid})
3742 {
3743 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3744 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3745 }
3746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003747 }
3748 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003749 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003750 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3751 }
3752 if($ShortName=~/\A(_Z|\?)/) {
3753 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3754 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003755
3756 if($ExtraDump) {
3757 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003759}
3760
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003761sub isConstType($$)
3762{
3763 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003764 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003765 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003766 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003767 }
3768 return ($Base{"Type"} eq "Const");
3769}
3770
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003771sub getTrivialName($$)
3772{
3773 my ($TypeInfoId, $TypeId) = @_;
3774 my %TypeAttr = ();
3775 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3776 if(not $TypeAttr{"Name"}) {
3777 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3778 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003779 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003780 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003781 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003782 if(isAnon($TypeAttr{"Name"}))
3783 {
3784 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003785 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003786 { # searching for a first not anon scope
3787 if($NSId eq $NameSpaceId) {
3788 last;
3789 }
3790 else
3791 {
3792 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3793 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003794 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003795 last;
3796 }
3797 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003798 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003799 }
3800 }
3801 else
3802 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003803 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003804 {
3805 if($NameSpaceId ne $TypeId) {
3806 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 }
3809 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003810 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003811 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3812 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003813 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003814 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003815 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003816 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003817 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003818 if($TypeAttr{"NameSpace"}) {
3819 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003822 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3823 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003824 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003825 if(my @TParams = getTParams($TypeId, "Type")) {
3826 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3827 }
3828 else {
3829 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 }
3832 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3833}
3834
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003835sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003836{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003837 my $TypeId = $_[0];
3838 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003839
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003840 my %TypeAttr = ();
3841
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003842 if($TemplateDecl{$Version}{$TypeId})
3843 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003844 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003845 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003847 setTypeAccess($TypeId, \%TypeAttr);
3848 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3849 if(isBuiltIn($TypeAttr{"Header"}))
3850 {
3851 delete($TypeAttr{"Header"});
3852 delete($TypeAttr{"Line"});
3853 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003854
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003855 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003856 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3857 if(not $TypeAttr{"Name"}) {
3858 return ();
3859 }
3860 if(not $TypeAttr{"NameSpace"}) {
3861 delete($TypeAttr{"NameSpace"});
3862 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003863
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003864 if($TypeAttr{"Type"} eq "Intrinsic")
3865 {
3866 if(defined $TypeAttr{"Header"})
3867 {
3868 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3869 { # support for SUSE 11.2
3870 # integer_type has srcp dump{1-2}.i
3871 delete($TypeAttr{"Header"});
3872 }
3873 }
3874 }
3875
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003876 my $Tmpl = undef;
3877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003878 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003879 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003880 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3881
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003882 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003883 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003884 foreach my $Pos (0 .. $#TParams)
3885 {
3886 my $Val = $TParams[$Pos];
3887 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3888
3889 if(not defined $TypeAttr{"Template"})
3890 {
3891 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3892
3893 if($Base{"Type"} eq "TemplateParam"
3894 or defined $Base{"Template"}) {
3895 $TypeAttr{"Template"} = 1;
3896 }
3897 }
3898
3899 if($Tmpl)
3900 {
3901 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3902 {
3903 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3904
3905 if($Val eq $Arg) {
3906 $TypeAttr{"Template"} = 1;
3907 }
3908 }
3909 }
3910 }
3911
3912 if($Tmpl)
3913 {
3914 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3915 {
3916 if($Pos>$#TParams)
3917 {
3918 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3919 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3920 }
3921 }
3922 }
3923 }
3924
3925 if($ADD_TMPL_INSTANCES)
3926 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003927 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003928 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003929 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003930 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003931 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003932 {
3933 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3934 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3935 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003936 }
3937 if(not getTreeAttr_Binf($TypeId))
3938 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003939 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3940 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3941 }
3942 }
3943 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003944 }
3945 }
3946 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003947
3948 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3949
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003950 if(my $Size = getSize($TypeId))
3951 {
3952 $Size = $Size/$BYTE_SIZE;
3953 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003954 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003955 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003956 {
3957 if($ExtraDump)
3958 {
3959 if(not defined $TypeAttr{"Memb"}
3960 and not $Tmpl)
3961 { # declaration only
3962 $TypeAttr{"Forward"} = 1;
3963 }
3964 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003965 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003966
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003967 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003968 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003969 {
3970 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003971 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003972 }
3973 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003974 or $TypeAttr{"Type"} eq "Class")
3975 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003976 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003977 if($Skip) {
3978 return ();
3979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003980 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003981 if(my $Algn = getAlgn($TypeId)) {
3982 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003984 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003985
3986 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3987 {
3988 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003989 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003990 {
3991 if(not isAnon($TypeAttr{"Name"})) {
3992 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3993 }
3994 }
3995 }
3996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003997 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003998 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3999 {
4000 my @Entries = split(/\n/, $VTable);
4001 foreach (1 .. $#Entries)
4002 {
4003 my $Entry = $Entries[$_];
4004 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004005 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004006 }
4007 }
4008 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004009
4010 if($TypeAttr{"Type"} eq "Enum")
4011 {
4012 if(not $TypeAttr{"NameSpace"})
4013 {
4014 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4015 {
4016 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004017 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004018 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004019 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004020 "Header"=>$TypeAttr{"Header"}
4021 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004022 if(isAnon($TypeAttr{"Name"}))
4023 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004024 if($ExtraDump
4025 or is_target_header($TypeAttr{"Header"}, $Version))
4026 {
4027 %{$Constants{$Version}{$MName}} = (
4028 "Value" => $MVal,
4029 "Header" => $TypeAttr{"Header"}
4030 );
4031 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004032 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004033 }
4034 }
4035 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004036 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004037 {
4038 if(defined $TypedefToAnon{$TypeId}) {
4039 $TypeAttr{"AnonTypedef"} = 1;
4040 }
4041 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004042
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004043 return %TypeAttr;
4044}
4045
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004046sub simplifyVTable($)
4047{
4048 my $Content = $_[0];
4049 if($Content=~s/ \[with (.+)]//)
4050 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4051 if(my @Elems = separate_Params($1, 0, 0))
4052 {
4053 foreach my $Elem (@Elems)
4054 {
4055 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4056 {
4057 my ($Arg, $Val) = ($1, $2);
4058
4059 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4060 $Content=~s/,\s*$Arg\b//g;
4061 }
4062 else {
4063 $Content=~s/\b$Arg\b/$Val/g;
4064 }
4065 }
4066 }
4067 }
4068 }
4069
4070 return $Content;
4071}
4072
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004073sub detect_lang($)
4074{
4075 my $TypeId = $_[0];
4076 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004077 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004078 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004079 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4080 }
4081 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004082 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004083 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004084 while($Fncs)
4085 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004086 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004087 return 1;
4088 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004089 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004090 }
4091 }
4092 return 0;
4093}
4094
4095sub setSpec($$)
4096{
4097 my ($TypeId, $TypeAttr) = @_;
4098 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4099 if($Info=~/\s+spec\s+/) {
4100 $TypeAttr->{"Spec"} = 1;
4101 }
4102}
4103
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004104sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004105{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004106 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004108 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004109 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004110 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 my $Pos = 0;
4112 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4113 {
4114 my ($Access, $BInfoId) = ($1, $2);
4115 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004116
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004117 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004118 { # class A<N>:public A<N-1>
4119 next;
4120 }
4121
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004122 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4123 if(not $CType or $CType eq "template_type_parm"
4124 or $CType eq "typename_type")
4125 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004126 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004128 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004129 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4131 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004132 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004133 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4134 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004135 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004136 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004137 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004138 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4139 }
4140 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004141 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004142 }
4143 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004144 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004145}
4146
4147sub getBinfClassId($)
4148{
4149 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004150 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4151 return $1;
4152 }
4153
4154 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004155}
4156
4157sub unmangledFormat($$)
4158{
4159 my ($Name, $LibVersion) = @_;
4160 $Name = uncover_typedefs($Name, $LibVersion);
4161 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4162 $Name=~s/\(\w+\)(\d)/$1/;
4163 return $Name;
4164}
4165
4166sub modelUnmangled($$)
4167{
4168 my ($InfoId, $Compiler) = @_;
4169 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4170 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4171 }
4172 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4173 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4174 $PureSignature = "~".$PureSignature;
4175 }
4176 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4177 {
4178 my (@Params, @ParamTypes) = ();
4179 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4180 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4181 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4182 }
4183 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4184 { # checking parameters
4185 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004186 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004187 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004188 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004189
4190 if($PName eq "this"
4191 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4192 {
4193 next;
4194 }
4195
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004196 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004197 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004198 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004199 }
4200 @ParamTypes = (@ParamTypes, $PTName);
4201 }
4202 if(@ParamTypes) {
4203 $PureSignature .= "(".join(", ", @ParamTypes).")";
4204 }
4205 else
4206 {
4207 if($Compiler eq "MSVC")
4208 {
4209 $PureSignature .= "(void)";
4210 }
4211 else
4212 { # GCC
4213 $PureSignature .= "()";
4214 }
4215 }
4216 $PureSignature = delete_keywords($PureSignature);
4217 }
4218 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4219 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004220 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004221 $PureSignature = $ClassName."::".$PureSignature;
4222 }
4223 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4224 $PureSignature = $NS."::".$PureSignature;
4225 }
4226 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4227 $PureSignature .= " const";
4228 }
4229 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4230 $PureSignature .= " volatile";
4231 }
4232 my $ShowReturn = 0;
4233 if($Compiler eq "MSVC"
4234 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4235 {
4236 $ShowReturn=1;
4237 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004238 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4239 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004240 {
4241 $ShowReturn=1;
4242 }
4243 if($ShowReturn)
4244 { # mangled names for template function specializations include return value
4245 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4246 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004247 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004248 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4249 $PureSignature = $ReturnName." ".$PureSignature;
4250 }
4251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004252 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004253}
4254
4255sub mangle_symbol($$$)
4256{ # mangling for simple methods
4257 # see gcc-4.6.0/gcc/cp/mangle.c
4258 my ($InfoId, $LibVersion, $Compiler) = @_;
4259 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4260 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4261 }
4262 my $Mangled = "";
4263 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004264 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004265 }
4266 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004267 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004268 }
4269 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4270}
4271
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004272sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004273{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004274 my ($InfoId, $LibVersion) = @_;
4275 return "";
4276}
4277
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004278sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004279{ # see gcc-4.6.0/gcc/cp/mangle.c
4280 my ($InfoId, $LibVersion) = @_;
4281 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004282 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004283 my %Repl = ();# SN_ replacements
4284 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4285 {
4286 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4287 if($MangledClass!~/\AN/) {
4288 $MangledClass = "N".$MangledClass;
4289 }
4290 else {
4291 $MangledClass=~s/E\Z//;
4292 }
4293 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4294 $MangledClass=~s/\AN/NV/;
4295 }
4296 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4297 $MangledClass=~s/\AN/NK/;
4298 }
4299 $Mangled .= $MangledClass;
4300 }
4301 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4302 { # mangled by name due to the absence of structured info
4303 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4304 if($MangledNS!~/\AN/) {
4305 $MangledNS = "N".$MangledNS;
4306 }
4307 else {
4308 $MangledNS=~s/E\Z//;
4309 }
4310 $Mangled .= $MangledNS;
4311 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004312 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004313 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004314 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004315 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004316 foreach (@TPos) {
4317 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4318 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004319 }
4320 elsif($TmplParams)
4321 { # remangling mode
4322 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004323 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004324 }
4325 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4326 $Mangled .= "C1";
4327 }
4328 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4329 $Mangled .= "D0";
4330 }
4331 elsif($ShortName)
4332 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004333 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4334 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004335 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004336 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004337 { # "const" global data is mangled as _ZL...
4338 $Mangled .= "L";
4339 }
4340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004341 if($ShortName=~/\Aoperator(\W.*)\Z/)
4342 {
4343 my $Op = $1;
4344 $Op=~s/\A[ ]+//g;
4345 if(my $OpMngl = $OperatorMangling{$Op}) {
4346 $Mangled .= $OpMngl;
4347 }
4348 else { # conversion operator
4349 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4350 }
4351 }
4352 else {
4353 $Mangled .= length($ShortName).$ShortName;
4354 }
4355 if(@TParams)
4356 { # templates
4357 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004358 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004359 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4360 }
4361 $Mangled .= "E";
4362 }
4363 if(not $ClassId and @TParams) {
4364 add_substitution($ShortName, \%Repl, 0);
4365 }
4366 }
4367 if($ClassId or $NameSpace) {
4368 $Mangled .= "E";
4369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004370 if(@TParams)
4371 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004372 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004373 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4374 }
4375 }
4376 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4377 {
4378 my @Params = ();
4379 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4380 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4381 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4382 }
4383 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4384 { # checking parameters
4385 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4386 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4387 }
4388 if(not @Params) {
4389 $Mangled .= "v";
4390 }
4391 }
4392 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4393 $Mangled = write_stdcxx_substitution($Mangled);
4394 if($Mangled eq "_Z") {
4395 return "";
4396 }
4397 return $Mangled;
4398}
4399
4400sub correct_incharge($$$)
4401{
4402 my ($InfoId, $LibVersion, $Mangled) = @_;
4403 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4404 {
4405 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004406 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004407 }
4408 }
4409 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4410 {
4411 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004412 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004413 }
4414 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004415 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004416 }
4417 }
4418 return $Mangled;
4419}
4420
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004421sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004422{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004423 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004424 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004425 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004426 return $Name;
4427 }
4428 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004429 while(my $CPos = find_center($TParams, "<"))
4430 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004431 $TParams = substr($TParams, $CPos);
4432 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004433 if($TParams=~s/\A<(.+)>\Z/$1/) {
4434 $Name=~s/<\Q$TParams\E>\Z//;
4435 }
4436 else
4437 { # error
4438 $TParams = "";
4439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004440 return ($Name, $TParams);
4441}
4442
4443sub get_sub_ns($)
4444{
4445 my $Name = $_[0];
4446 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004447 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004448 {
4449 push(@NS, substr($Name, 0, $CPos));
4450 $Name = substr($Name, $CPos);
4451 $Name=~s/\A:://;
4452 }
4453 return (join("::", @NS), $Name);
4454}
4455
4456sub mangle_ns($$$)
4457{
4458 my ($Name, $LibVersion, $Repl) = @_;
4459 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4460 {
4461 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4462 $Mangled=~s/\AN(.+)E\Z/$1/;
4463 return $Mangled;
4464
4465 }
4466 else
4467 {
4468 my ($MangledNS, $SubNS) = ("", "");
4469 ($SubNS, $Name) = get_sub_ns($Name);
4470 if($SubNS) {
4471 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4472 }
4473 $MangledNS .= length($Name).$Name;
4474 add_substitution($MangledNS, $Repl, 0);
4475 return $MangledNS;
4476 }
4477}
4478
4479sub mangle_param($$$)
4480{
4481 my ($PTid, $LibVersion, $Repl) = @_;
4482 my ($MPrefix, $Mangled) = ("", "");
4483 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004484 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004485 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004486 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004487 if(not $BaseType_Name) {
4488 return "";
4489 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004490 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004491 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004492 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4493 while($Suffix=~/(&|\*|const)\Z/)
4494 {
4495 if($Suffix=~s/[ ]*&\Z//) {
4496 $MPrefix .= "R";
4497 }
4498 if($Suffix=~s/[ ]*\*\Z//) {
4499 $MPrefix .= "P";
4500 }
4501 if($Suffix=~s/[ ]*const\Z//)
4502 {
4503 if($MPrefix=~/R|P/
4504 or $Suffix=~/&|\*/) {
4505 $MPrefix .= "K";
4506 }
4507 }
4508 if($Suffix=~s/[ ]*volatile\Z//) {
4509 $MPrefix .= "V";
4510 }
4511 #if($Suffix=~s/[ ]*restrict\Z//) {
4512 #$MPrefix .= "r";
4513 #}
4514 }
4515 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4516 $Mangled .= $Token;
4517 }
4518 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4519 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004520 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004521 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004522 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004523 foreach (@TPos) {
4524 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4525 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004526 }
4527 elsif($TmplParams)
4528 { # remangling mode
4529 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004530 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004531 }
4532 my $MangledNS = "";
4533 my ($SubNS, $SName) = get_sub_ns($ShortName);
4534 if($SubNS) {
4535 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4536 }
4537 $MangledNS .= length($SName).$SName;
4538 if(@TParams) {
4539 add_substitution($MangledNS, $Repl, 0);
4540 }
4541 $Mangled .= "N".$MangledNS;
4542 if(@TParams)
4543 { # templates
4544 $Mangled .= "I";
4545 foreach my $TParam (@TParams) {
4546 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4547 }
4548 $Mangled .= "E";
4549 }
4550 $Mangled .= "E";
4551 }
4552 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4553 {
4554 if($BaseType{"Type"} eq "MethodPtr") {
4555 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4556 }
4557 else {
4558 $Mangled .= "PF";
4559 }
4560 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4561 my @Params = keys(%{$BaseType{"Param"}});
4562 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4563 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4564 }
4565 if(not @Params) {
4566 $Mangled .= "v";
4567 }
4568 $Mangled .= "E";
4569 }
4570 elsif($BaseType{"Type"} eq "FieldPtr")
4571 {
4572 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4573 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4574 }
4575 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4576 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4577 {
4578 if($Mangled eq $Optimized)
4579 {
4580 if($ShortName!~/::/)
4581 { # remove "N ... E"
4582 if($MPrefix) {
4583 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4584 }
4585 else {
4586 $Mangled=~s/\AN(.+)E\Z/$1/g;
4587 }
4588 }
4589 }
4590 else {
4591 $Mangled = $Optimized;
4592 }
4593 }
4594 add_substitution($Mangled, $Repl, 1);
4595 return $Mangled;
4596}
4597
4598sub mangle_template_param($$$)
4599{ # types + literals
4600 my ($TParam, $LibVersion, $Repl) = @_;
4601 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4602 return mangle_param($TPTid, $LibVersion, $Repl);
4603 }
4604 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4605 { # class_name<1u>::method(...)
4606 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4607 }
4608 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4609 { # class_name<(signed char)1>::method(...)
4610 return "L".$IntrinsicMangling{$1}.$2."E";
4611 }
4612 elsif($TParam eq "true")
4613 { # class_name<true>::method(...)
4614 return "Lb1E";
4615 }
4616 elsif($TParam eq "false")
4617 { # class_name<true>::method(...)
4618 return "Lb0E";
4619 }
4620 else { # internal error
4621 return length($TParam).$TParam;
4622 }
4623}
4624
4625sub add_substitution($$$)
4626{
4627 my ($Value, $Repl, $Rec) = @_;
4628 if($Rec)
4629 { # subtypes
4630 my @Subs = ($Value);
4631 while($Value=~s/\A(R|P|K)//) {
4632 push(@Subs, $Value);
4633 }
4634 foreach (reverse(@Subs)) {
4635 add_substitution($_, $Repl, 0);
4636 }
4637 return;
4638 }
4639 return if($Value=~/\AS(\d*)_\Z/);
4640 $Value=~s/\AN(.+)E\Z/$1/g;
4641 return if(defined $Repl->{$Value});
4642 return if(length($Value)<=1);
4643 return if($StdcxxMangling{$Value});
4644 # check for duplicates
4645 my $Base = $Value;
4646 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4647 {
4648 my $Num = $Repl->{$Type};
4649 my $Replace = macro_mangle($Num);
4650 $Base=~s/\Q$Replace\E/$Type/;
4651 }
4652 if(my $OldNum = $Repl->{$Base})
4653 {
4654 $Repl->{$Value} = $OldNum;
4655 return;
4656 }
4657 my @Repls = sort {$b<=>$a} values(%{$Repl});
4658 if(@Repls) {
4659 $Repl->{$Value} = $Repls[0]+1;
4660 }
4661 else {
4662 $Repl->{$Value} = -1;
4663 }
4664 # register duplicates
4665 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004666 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004667 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4668 {
4669 next if($Base eq $Type);
4670 my $Num = $Repl->{$Type};
4671 my $Replace = macro_mangle($Num);
4672 $Base=~s/\Q$Type\E/$Replace/;
4673 $Repl->{$Base} = $Repl->{$Value};
4674 }
4675}
4676
4677sub macro_mangle($)
4678{
4679 my $Num = $_[0];
4680 if($Num==-1) {
4681 return "S_";
4682 }
4683 else
4684 {
4685 my $Code = "";
4686 if($Num<10)
4687 { # S0_, S1_, S2_, ...
4688 $Code = $Num;
4689 }
4690 elsif($Num>=10 and $Num<=35)
4691 { # SA_, SB_, SC_, ...
4692 $Code = chr(55+$Num);
4693 }
4694 else
4695 { # S10_, S11_, S12_
4696 $Code = $Num-26; # 26 is length of english alphabet
4697 }
4698 return "S".$Code."_";
4699 }
4700}
4701
4702sub write_stdcxx_substitution($)
4703{
4704 my $Mangled = $_[0];
4705 if($StdcxxMangling{$Mangled}) {
4706 return $StdcxxMangling{$Mangled};
4707 }
4708 else
4709 {
4710 my @Repls = keys(%StdcxxMangling);
4711 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4712 foreach my $MangledType (@Repls)
4713 {
4714 my $Replace = $StdcxxMangling{$MangledType};
4715 #if($Mangled!~/$Replace/) {
4716 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4717 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4718 #}
4719 }
4720 }
4721 return $Mangled;
4722}
4723
4724sub write_substitution($$)
4725{
4726 my ($Mangled, $Repl) = @_;
4727 if(defined $Repl->{$Mangled}
4728 and my $MnglNum = $Repl->{$Mangled}) {
4729 $Mangled = macro_mangle($MnglNum);
4730 }
4731 else
4732 {
4733 my @Repls = keys(%{$Repl});
4734 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4735 # FIXME: how to apply replacements? by num or by pos
4736 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4737 foreach my $MangledType (@Repls)
4738 {
4739 my $Replace = macro_mangle($Repl->{$MangledType});
4740 if($Mangled!~/$Replace/) {
4741 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4742 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4743 }
4744 }
4745 }
4746 return $Mangled;
4747}
4748
4749sub delete_keywords($)
4750{
4751 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004752 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004753 return $TypeName;
4754}
4755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004756sub uncover_typedefs($$)
4757{
4758 my ($TypeName, $LibVersion) = @_;
4759 return "" if(not $TypeName);
4760 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4761 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4762 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004763 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004764 while($TypeName_New ne $TypeName_Pre)
4765 {
4766 $TypeName_Pre = $TypeName_New;
4767 my $TypeName_Copy = $TypeName_New;
4768 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004769 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004771 if(not $Intrinsic_Keywords{$1}) {
4772 $Words{$1} = 1;
4773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004774 }
4775 foreach my $Word (keys(%Words))
4776 {
4777 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4778 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004779 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004780 if($BaseType_Name=~/\([\*]+\)/)
4781 { # FuncPtr
4782 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4783 {
4784 my $Type_Suffix = $1;
4785 $TypeName_New = $BaseType_Name;
4786 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004787 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004788 }
4789 }
4790 }
4791 else
4792 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004793 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004794 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004795 }
4796 }
4797 }
4798 }
4799 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4800}
4801
4802sub isInternal($)
4803{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004804 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4805 {
4806 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4807 {
4808 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4809 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4810 return 1;
4811 }
4812 }
4813 }
4814 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004815}
4816
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004817sub getDataVal($$)
4818{
4819 my ($InfoId, $TypeId) = @_;
4820 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4821 {
4822 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4823 {
4824 if(defined $LibInfo{$Version}{"info_type"}{$1}
4825 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004826 {
4827 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004828 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004829 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4830 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004831 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004832 if(my $Addr = getTreeAttr_Op($1)) {
4833 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004834 }
4835 }
4836 }
4837 }
4838 else {
4839 return getInitVal($1, $TypeId);
4840 }
4841 }
4842 }
4843 return undef;
4844}
4845
4846sub getInitVal($$)
4847{
4848 my ($InfoId, $TypeId) = @_;
4849 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4850 {
4851 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4852 {
4853 if($InfoType eq "integer_cst")
4854 {
4855 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004856 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004857 { # characters
4858 $Val = chr($Val);
4859 }
4860 return $Val;
4861 }
4862 elsif($InfoType eq "string_cst") {
4863 return getNodeStrCst($InfoId);
4864 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004865 elsif($InfoType eq "var_decl")
4866 {
4867 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4868 return $Name;
4869 }
4870 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004871 }
4872 }
4873 return undef;
4874}
4875
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004876sub set_Class_And_Namespace($)
4877{
4878 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004879 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004880 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004881 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004882 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004883 my $NSInfoId = $1;
4884 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4885 {
4886 if($InfoType eq "namespace_decl") {
4887 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4888 }
4889 elsif($InfoType eq "record_type") {
4890 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4891 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004893 }
4894 }
4895 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4896 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004897 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004898 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004899 { # skip
4900 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004902 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004903
4904 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004905}
4906
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004907sub debugMangling($)
4908{
4909 my $LibVersion = $_[0];
4910 my %Mangled = ();
4911 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4912 {
4913 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4914 {
4915 if($Mngl=~/\A(_Z|\?)/) {
4916 $Mangled{$Mngl}=$InfoId;
4917 }
4918 }
4919 }
4920 translateSymbols(keys(%Mangled), $LibVersion);
4921 foreach my $Mngl (keys(%Mangled))
4922 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004923 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4924 my $U2 = $tr_name{$Mngl};
4925 if($U1 ne $U2) {
4926 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004927 }
4928 }
4929}
4930
4931sub linkSymbol($)
4932{ # link symbols from shared libraries
4933 # with the symbols from header files
4934 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004935 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004936 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004937 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4938 or $EMERGENCY_MODE_48)
4939 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4940 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03004941 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004942 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004943 {
4944 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4945 return correct_incharge($InfoId, $Version, $Mangled);
4946 }
4947 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004948 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004949 or not $BinaryOnly
4950 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004951 { # 1. --headers-only mode
4952 # 2. not mangled src-only symbols
4953 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4954 return $Mangled;
4955 }
4956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004957 }
4958 return "";
4959}
4960
4961sub setLanguage($$)
4962{
4963 my ($LibVersion, $Lang) = @_;
4964 if(not $UserLang) {
4965 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4966 }
4967}
4968
4969sub getSymbolInfo($)
4970{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004971 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004972 if(isInternal($InfoId)) {
4973 return;
4974 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004975 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4976 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004977 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4978 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004979 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004980 return;
4981 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004982 setFuncAccess($InfoId);
4983 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004984 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4985 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004986 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004987 return;
4988 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004989
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004990 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004991 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004992 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004993 if(not defined $TypeInfo{$Version}{$Return}
4994 or not $TypeInfo{$Version}{$Return}{"Name"})
4995 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004996 delete($SymbolInfo{$Version}{$InfoId});
4997 return;
4998 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004999 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005000 }
5001 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5002 {
5003 if(defined $MissedTypedef{$Version}{$Rid})
5004 {
5005 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5006 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5007 }
5008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005009 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005010 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5011 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005012 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005013 my $Orig = getFuncOrig($InfoId);
5014 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005015 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5016 {
5017 delete($SymbolInfo{$Version}{$InfoId});
5018 return;
5019 }
5020
5021 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005022 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005023 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005024 return;
5025 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005026
5027 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005028 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005029 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5030
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005031 my @TParams = getTParams($Orig, "Func");
5032 if(not @TParams)
5033 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005034 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005035 return;
5036 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005037 foreach my $Pos (0 .. $#TParams)
5038 {
5039 my $Val = $TParams[$Pos];
5040 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5041
5042 if($Tmpl)
5043 {
5044 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5045 {
5046 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5047 }
5048 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005049 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005050
5051 if($Tmpl)
5052 {
5053 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5054 {
5055 if($Pos>$#TParams)
5056 {
5057 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5058 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5059 }
5060 }
5061 }
5062
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005063 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5064 { # operator<< <T>, operator>> <T>
5065 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5066 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005067 if(@TParams) {
5068 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5069 }
5070 else {
5071 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5072 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005073 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005074 }
5075 else
5076 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005077 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005078 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005079 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5080 {
5081 if($OSgroup eq "windows")
5082 { # cut the offset
5083 $MnglName=~s/\@\d+\Z//g;
5084 }
5085 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5086
5087 # NOTE: mangling of some symbols may change depending on GCC version
5088 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5089 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5090 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005091
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005092 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005093 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005094 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005095 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005096 return;
5097 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005098 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005099 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005100 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005101 if($Skip)
5102 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005103 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005104 return;
5105 }
5106 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005107 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5108 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5109 }
5110
5111 if(set_Class_And_Namespace($InfoId))
5112 {
5113 delete($SymbolInfo{$Version}{$InfoId});
5114 return;
5115 }
5116
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005117 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5118 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005119 if(not defined $TypeInfo{$Version}{$ClassId}
5120 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5121 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005122 delete($SymbolInfo{$Version}{$InfoId});
5123 return;
5124 }
5125 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005126 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5127 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005128 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005129 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005130 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005131 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005132 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005133 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 }
5135 if($COMMON_LANGUAGE{$Version} eq "C++")
5136 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005137 # C++ or --headers-only mode
5138 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005140 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5141 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005142 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005143 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005144 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005145 if(my $Mangled = linkSymbol($InfoId)) {
5146 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 }
5148 }
5149 if($OStarget eq "windows")
5150 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005151 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005152 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005153 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005155 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005156 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005157 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005158 }
5159 }
5160 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005161 else
5162 { # not mangled in C
5163 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5164 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005165 if(not $CheckHeadersOnly
5166 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5167 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5168 {
5169 my $Incorrect = 0;
5170
5171 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5172 {
5173 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5174 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5175 { # mangled in the TU dump, but not mangled in the library
5176 $Incorrect = 1;
5177 }
5178 }
5179 else
5180 {
5181 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5182 { # all C++ functions are not mangled in the TU dump
5183 $Incorrect = 1;
5184 }
5185 }
5186 if($Incorrect)
5187 {
5188 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5189 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5190 }
5191 }
5192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005193 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005194 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005195 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 return;
5197 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005198 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005199 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005200 { # identify virtual and pure virtual functions
5201 # NOTE: constructors cannot be virtual
5202 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5203 # in the TU dump, so taking it from the original symbol
5204 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5205 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5206 { # NOTE: D2 destructors are not present in a v-table
5207 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005209 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005210 if(isInline($InfoId)) {
5211 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005212 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005213 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005214 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005216 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5217 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005218 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005219 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005220 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005221 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005222 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005223 }
5224 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005225 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5226 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005227 if(not $ExtraDump)
5228 {
5229 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5230 { # non-target symbols
5231 delete($SymbolInfo{$Version}{$InfoId});
5232 return;
5233 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5237 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5238 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5239 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005240 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005241 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5242 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005243 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 return;
5245 }
5246 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005247 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005249 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 return;
5253 }
5254 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005255 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005256 }
5257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005258 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5259 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5260 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005262 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5263 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005264 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005265 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005267 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 }
5269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005270 if(getFuncLink($InfoId) eq "Static") {
5271 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005272 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005273 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5274 {
5275 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5276 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005277 if($Unmangled=~/\.\_\d/)
5278 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005279 delete($SymbolInfo{$Version}{$InfoId});
5280 return;
5281 }
5282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005283 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005284
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005285 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5286 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005288 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5289 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005291
5292 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5293 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5294 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005295
5296 if($ExtraDump) {
5297 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5298 }
5299}
5300
5301sub guessHeader($)
5302{
5303 my $InfoId = $_[0];
5304 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5305 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5306 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5307 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5308 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5309 {
5310 if(get_filename($HPath) eq $Header)
5311 {
5312 my $HDir = get_filename(get_dirname($HPath));
5313 if($HDir ne "include"
5314 and $HDir=~/\A[a-z]+\Z/i) {
5315 return join_P($HDir, $Header);
5316 }
5317 }
5318 }
5319 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005320}
5321
5322sub isInline($)
5323{ # "body: undefined" in the tree
5324 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5326 {
5327 if($Info=~/ undefined /i) {
5328 return 0;
5329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005330 }
5331 return 1;
5332}
5333
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005334sub hasThrow($)
5335{
5336 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5337 {
5338 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5339 return getTreeAttr_Unql($1, "unql");
5340 }
5341 }
5342 return 1;
5343}
5344
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345sub getTypeId($)
5346{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005347 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5348 {
5349 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5350 return $1;
5351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005352 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005353 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005354}
5355
5356sub setTypeMemb($$)
5357{
5358 my ($TypeId, $TypeAttr) = @_;
5359 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005360 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005361 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 if($TypeType eq "Enum")
5363 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005364 my $MInfoId = getTreeAttr_Csts($TypeId);
5365 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005367 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5368 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005369 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005370 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5371 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005372 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005373 }
5374 }
5375 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5376 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005377 my $MInfoId = getTreeAttr_Flds($TypeId);
5378 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005379 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005380 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5381 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005382 if(not $IType or $IType ne "field_decl")
5383 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005384
5385 if($IType eq "var_decl")
5386 { # static field
5387 $StaticFields = 1;
5388 }
5389
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005390 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005391 next;
5392 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005393 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005394 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005395 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005396 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005397 }
5398 if(not $StructMembName)
5399 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005400 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005401 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005402 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005403 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5404 if(isAnon($UnnamedTName))
5405 { # rename unnamed fields to unnamed0, unnamed1, ...
5406 $StructMembName = "unnamed".($UnnamedPos++);
5407 }
5408 }
5409 }
5410 if(not $StructMembName)
5411 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005412 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005413 next;
5414 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005415 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005416 if(defined $MissedTypedef{$Version}{$MembTypeId})
5417 {
5418 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5419 $MembTypeId = $AddedTid;
5420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005421 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005422
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005423 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5424 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005425 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005426 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005427 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5428 }
5429 if($MInfo=~/spec:\s*mutable /)
5430 { # mutable fields
5431 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005433 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005434 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5435 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005436 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005437 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005438 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005439 }
5440 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005441 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005442 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5443 { # template
5444 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5445 }
5446 else {
5447 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005449 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005450
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005451 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005452 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 }
5454 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005455
5456 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005457}
5458
5459sub setFuncParams($)
5460{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005461 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005462 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005463
5464 my $FType = getFuncType($InfoId);
5465
5466 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005468 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5469 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005470 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005471 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005472 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5473 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005474 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005475 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5476 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005477 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005478 else
5479 { # skip
5480 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005481 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005482 # skip "this"-parameter
5483 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005484 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005485 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005486 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005487 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005488 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5489 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5490 if(not $ParamName)
5491 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005492 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005493 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005494 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5495 {
5496 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5497 $ParamTypeId = $AddedTid;
5498 }
5499 }
5500 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005501 if(not $PType or $PType eq "Unknown") {
5502 return 1;
5503 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005504 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005505 if(not $PTName) {
5506 return 1;
5507 }
5508 if($PTName eq "void") {
5509 last;
5510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005511 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005512 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005514 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005515 $ParamInfoId = getNextElem($ParamInfoId);
5516 next;
5517 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005518 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005519
5520 if(my %Base = get_BaseType($ParamTypeId, $Version))
5521 {
5522 if(defined $Base{"Template"}) {
5523 return 1;
5524 }
5525 }
5526
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005527 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005528 if(my $Algn = getAlgn($ParamInfoId)) {
5529 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5532 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005533 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005534 }
5535 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005536 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005537 if($ParamName ne "this" or $FType ne "Method") {
5538 $PPos += 1;
5539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005540 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005541 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005542 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 }
5544 return 0;
5545}
5546
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005547sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005548{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005549 my ($InfoId, $Vtt_Pos) = @_;
5550 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005551 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005552 my $FType = getFuncType($InfoId);
5553
5554 if($FType eq "Method")
5555 {
5556 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005557 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005558 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005559 if(not $ParamListElemId)
5560 { # foo(...)
5561 return 1;
5562 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005564 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005566 { # actual params: may differ from formal args
5567 # formal int*const
5568 # actual: int*
5569 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005570 {
5571 $Vtt_Pos=-1;
5572 $ParamListElemId = getNextElem($ParamListElemId);
5573 next;
5574 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005575 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5576 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005577 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005578 $HaveVoid = 1;
5579 last;
5580 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005581 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005582 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005583 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5584 {
5585 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5586 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5587 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005588 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005589 }
5590 }
5591 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5592 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005593 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005594 { # params
5595 if($OldId ne $ParamTypeId)
5596 {
5597 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5598 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5599
5600 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5601 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5602 }
5603 }
5604 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005605 }
5606 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005607 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005608 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005609 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5610 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005611 if($PurpType eq "nop_expr")
5612 { # func ( const char* arg = (const char*)(void*)0 )
5613 $PurpId = getTreeAttr_Op($PurpId);
5614 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005615 my $Val = getInitVal($PurpId, $ParamTypeId);
5616 if(defined $Val) {
5617 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005619 }
5620 }
5621 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005622 if($Pos!=0 or $FType ne "Method") {
5623 $PPos += 1;
5624 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005625 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005626 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005627 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628}
5629
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005630sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005631{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005632 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5633 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005634 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5635 return $1;
5636 }
5637 }
5638 return "";
5639}
5640
5641sub getTreeAttr_Chain($)
5642{
5643 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5644 {
5645 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5646 return $1;
5647 }
5648 }
5649 return "";
5650}
5651
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005652sub getTreeAttr_Unql($)
5653{
5654 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5655 {
5656 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5657 return $1;
5658 }
5659 }
5660 return "";
5661}
5662
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005663sub getTreeAttr_Scpe($)
5664{
5665 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5666 {
5667 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5668 return $1;
5669 }
5670 }
5671 return "";
5672}
5673
5674sub getTreeAttr_Type($)
5675{
5676 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5677 {
5678 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5679 return $1;
5680 }
5681 }
5682 return "";
5683}
5684
5685sub getTreeAttr_Name($)
5686{
5687 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5688 {
5689 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5690 return $1;
5691 }
5692 }
5693 return "";
5694}
5695
5696sub getTreeAttr_Mngl($)
5697{
5698 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5699 {
5700 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5701 return $1;
5702 }
5703 }
5704 return "";
5705}
5706
5707sub getTreeAttr_Prms($)
5708{
5709 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5710 {
5711 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5712 return $1;
5713 }
5714 }
5715 return "";
5716}
5717
5718sub getTreeAttr_Fncs($)
5719{
5720 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5721 {
5722 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5723 return $1;
5724 }
5725 }
5726 return "";
5727}
5728
5729sub getTreeAttr_Csts($)
5730{
5731 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5732 {
5733 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5734 return $1;
5735 }
5736 }
5737 return "";
5738}
5739
5740sub getTreeAttr_Purp($)
5741{
5742 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5743 {
5744 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5745 return $1;
5746 }
5747 }
5748 return "";
5749}
5750
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005751sub getTreeAttr_Op($)
5752{
5753 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5754 {
5755 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5756 return $1;
5757 }
5758 }
5759 return "";
5760}
5761
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005762sub getTreeAttr_Valu($)
5763{
5764 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5765 {
5766 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5767 return $1;
5768 }
5769 }
5770 return "";
5771}
5772
5773sub getTreeAttr_Flds($)
5774{
5775 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5776 {
5777 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5778 return $1;
5779 }
5780 }
5781 return "";
5782}
5783
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005784sub getTreeAttr_Binf($)
5785{
5786 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5787 {
5788 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5789 return $1;
5790 }
5791 }
5792 return "";
5793}
5794
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005795sub getTreeAttr_Args($)
5796{
5797 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5798 {
5799 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005800 return $1;
5801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005802 }
5803 return "";
5804}
5805
5806sub getTreeValue($)
5807{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005808 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5809 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005810 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5811 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005813 }
5814 return "";
5815}
5816
5817sub getTreeAccess($)
5818{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005819 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005820 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005821 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5822 {
5823 my $Access = $1;
5824 if($Access eq "prot") {
5825 return "protected";
5826 }
5827 elsif($Access eq "priv") {
5828 return "private";
5829 }
5830 }
5831 elsif($Info=~/ protected /)
5832 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005833 return "protected";
5834 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005835 elsif($Info=~/ private /)
5836 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005837 return "private";
5838 }
5839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005840 return "public";
5841}
5842
5843sub setFuncAccess($)
5844{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005845 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005846 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005847 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005848 }
5849 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005850 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005851 }
5852}
5853
5854sub setTypeAccess($$)
5855{
5856 my ($TypeId, $TypeAttr) = @_;
5857 my $Access = getTreeAccess($TypeId);
5858 if($Access eq "protected") {
5859 $TypeAttr->{"Protected"} = 1;
5860 }
5861 elsif($Access eq "private") {
5862 $TypeAttr->{"Private"} = 1;
5863 }
5864}
5865
5866sub setFuncKind($)
5867{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005868 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5869 {
5870 if($Info=~/pseudo tmpl/) {
5871 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5872 }
5873 elsif($Info=~/ constructor /) {
5874 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5875 }
5876 elsif($Info=~/ destructor /) {
5877 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5878 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005879 }
5880}
5881
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005882sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005884 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5885 {
5886 if($Info=~/spec[ ]*:[ ]*pure /) {
5887 return "PureVirt";
5888 }
5889 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5890 return "Virt";
5891 }
5892 elsif($Info=~/ pure\s+virtual /)
5893 { # support for old GCC versions
5894 return "PureVirt";
5895 }
5896 elsif($Info=~/ virtual /)
5897 { # support for old GCC versions
5898 return "Virt";
5899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005900 }
5901 return "";
5902}
5903
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005904sub getFuncLink($)
5905{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005906 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5907 {
5908 if($Info=~/link[ ]*:[ ]*static /) {
5909 return "Static";
5910 }
5911 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005912 return $1;
5913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005914 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005915 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005916}
5917
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005918sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005919{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005920 my ($Symbol, $LibVersion) = @_;
5921 return "" if(not $Symbol or not $LibVersion);
5922 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5923 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005925 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5926 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5927 }
5928 }
5929 if($NS)
5930 {
5931 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5932 return $NS;
5933 }
5934 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005935 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005936 while($NS=~s/::[^:]+\Z//)
5937 {
5938 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5939 return $NS;
5940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005941 }
5942 }
5943 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005944
5945 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005946}
5947
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005948sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005949{
5950 my ($TypeName, $LibVersion) = @_;
5951 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005952 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005953 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005954 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5955 return $NS;
5956 }
5957 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005958 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005959 while($NS=~s/::[^:]+\Z//)
5960 {
5961 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5962 return $NS;
5963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005964 }
5965 }
5966 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005967 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005968}
5969
5970sub getNameSpace($)
5971{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005972 my $InfoId = $_[0];
5973 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005974 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005975 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005976 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005977 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005978 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005979 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5980 {
5981 my $NameSpace = getTreeStr($1);
5982 if($NameSpace eq "::")
5983 { # global namespace
5984 return "";
5985 }
5986 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5987 $NameSpace = $BaseNameSpace."::".$NameSpace;
5988 }
5989 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5990 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005991 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005992 else {
5993 return "";
5994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005996 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005997 { # inside data type
5998 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5999 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006000 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006002 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006003 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006004}
6005
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006006sub getEnumMembVal($)
6007{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006008 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006009 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006010 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6011 {
6012 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6013 {
6014 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6015 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6016 return getTreeValue($1);
6017 }
6018 else
6019 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6020 return getTreeValue($1);
6021 }
6022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006023 }
6024 }
6025 return "";
6026}
6027
6028sub getSize($)
6029{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6031 {
6032 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6033 return getTreeValue($1);
6034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006036 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037}
6038
6039sub getAlgn($)
6040{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6042 {
6043 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6044 return $1;
6045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006047 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006048}
6049
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006050sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006052 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6053 {
6054 if($Info=~/ bitfield /) {
6055 return getSize($_[0]);
6056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006058 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059}
6060
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006061sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006063 if(my $Chan = getTreeAttr_Chan($_[0])) {
6064 return $Chan;
6065 }
6066 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6067 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006069 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006070}
6071
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006072sub registerHeader($$)
6073{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006075 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006076 return "";
6077 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006078 if(is_abs($Header) and not -f $Header)
6079 { # incorrect absolute path
6080 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006082 if(skipHeader($Header, $LibVersion))
6083 { # skip
6084 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006086 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6087 {
6088 detect_header_includes($Header_Path, $LibVersion);
6089
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006090 if(defined $Tolerance and $Tolerance=~/3/)
6091 { # 3 - skip headers that include non-Linux headers
6092 if($OSgroup ne "windows")
6093 {
6094 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6095 {
6096 if(specificHeader($Inc, "windows")) {
6097 return "";
6098 }
6099 }
6100 }
6101 }
6102
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006103 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6104 { # redirect
6105 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6106 or skipHeader($RHeader_Path, $LibVersion))
6107 { # skip
6108 return "";
6109 }
6110 $Header_Path = $RHeader_Path;
6111 }
6112 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6113 { # skip
6114 return "";
6115 }
6116
6117 if(my $HName = get_filename($Header_Path))
6118 { # register
6119 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6120 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6121 }
6122
6123 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6124 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006125 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006126 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006127 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006128 }
6129
6130 if($CheckHeadersOnly
6131 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6132 { # /usr/include/c++/4.6.1/...
6133 $STDCXX_TESTING = 1;
6134 }
6135
6136 return $Header_Path;
6137 }
6138 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006139}
6140
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006141sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006142{
6143 my ($Dir, $WithDeps, $LibVersion) = @_;
6144 $Dir=~s/[\/\\]+\Z//g;
6145 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006146 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006147
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006148 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006149 if($WithDeps)
6150 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006151 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6152 return;
6153 }
6154 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6155 $Mode = "DepsOnly";
6156 }
6157 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006158 else
6159 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006160 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6161 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6162 return;
6163 }
6164 }
6165 $Header_Dependency{$LibVersion}{$Dir} = 1;
6166 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6167 if($Mode eq "DepsOnly")
6168 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006169 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006170 $Header_Dependency{$LibVersion}{$Path} = 1;
6171 }
6172 return;
6173 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006174 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006175 {
6176 if($WithDeps)
6177 {
6178 my $SubDir = $Path;
6179 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6180 { # register all sub directories
6181 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6182 }
6183 }
6184 next if(is_not_header($Path));
6185 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006186 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006187 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006188 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6189 }
6190 }
6191 if(get_filename($Dir) eq "include")
6192 { # search for "lib/include/" directory
6193 my $LibDir = $Dir;
6194 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006195 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 }
6197 }
6198}
6199
6200sub parse_redirect($$$)
6201{
6202 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006203 my @Errors = ();
6204 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6205 push(@Errors, $1);
6206 }
6207 my $Redirect = "";
6208 foreach (@Errors)
6209 {
6210 s/\s{2,}/ /g;
6211 if(/(only|must\ include
6212 |update\ to\ include
6213 |replaced\ with
6214 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006215 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006216 {
6217 $Redirect = $2;
6218 last;
6219 }
6220 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6221 {
6222 $Redirect = $2;
6223 last;
6224 }
6225 elsif(/this\ header\ should\ not\ be\ used
6226 |programs\ should\ not\ directly\ include
6227 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6228 |is\ not\ supported\ API\ for\ general\ use
6229 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006230 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006231 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6232 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6233 }
6234 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006235 if($Redirect)
6236 {
6237 $Redirect=~s/\A<//g;
6238 $Redirect=~s/>\Z//g;
6239 }
6240 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006241}
6242
6243sub parse_includes($$)
6244{
6245 my ($Content, $Path) = @_;
6246 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006247 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006248 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006249 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006250 my $Method = substr($Header, 0, 1, "");
6251 substr($Header, length($Header)-1, 1, "");
6252 $Header = path_format($Header, $OSgroup);
6253 if($Method eq "\"" or is_abs($Header))
6254 {
6255 if(-e join_P(get_dirname($Path), $Header))
6256 { # relative path exists
6257 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006258 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006259 else
6260 { # include "..." that doesn't exist is equal to include <...>
6261 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006263 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006264 else {
6265 $Includes{$Header} = 1;
6266 }
6267 }
6268 if($ExtraInfo)
6269 {
6270 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6271 { # FT_FREETYPE_H
6272 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006273 }
6274 }
6275 return \%Includes;
6276}
6277
6278sub ignore_path($)
6279{
6280 my $Path = $_[0];
6281 if($Path=~/\~\Z/)
6282 {# skipping system backup files
6283 return 1;
6284 }
6285 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6286 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6287 return 1;
6288 }
6289 return 0;
6290}
6291
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006292sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006293{
6294 my ($ArrRef, $W) = @_;
6295 return if(length($W)<2);
6296 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6297}
6298
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006299sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006300{
6301 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006302
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006303 $H1=~s/\.[a-z]+\Z//ig;
6304 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006305
6306 my $Hname1 = get_filename($H1);
6307 my $Hname2 = get_filename($H2);
6308 my $HDir1 = get_dirname($H1);
6309 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006310 my $Dirname1 = get_filename($HDir1);
6311 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006312
6313 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6314 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6315
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006316 if($_[0] eq $_[1]
6317 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006318 return 0;
6319 }
6320 elsif($H1=~/\A\Q$H2\E/) {
6321 return 1;
6322 }
6323 elsif($H2=~/\A\Q$H1\E/) {
6324 return -1;
6325 }
6326 elsif($HDir1=~/\Q$Hname1\E/i
6327 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006328 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006329 return -1;
6330 }
6331 elsif($HDir2=~/\Q$Hname2\E/i
6332 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006333 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006334 return 1;
6335 }
6336 elsif($Hname1=~/\Q$Dirname1\E/i
6337 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006338 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006339 return -1;
6340 }
6341 elsif($Hname2=~/\Q$Dirname2\E/i
6342 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006343 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006344 return 1;
6345 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006346 elsif($Hname1=~/(config|lib|util)/i
6347 and $Hname2!~/(config|lib|util)/i)
6348 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349 return -1;
6350 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006351 elsif($Hname2=~/(config|lib|util)/i
6352 and $Hname1!~/(config|lib|util)/i)
6353 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006354 return 1;
6355 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006356 else
6357 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006358 my $R1 = checkRelevance($H1);
6359 my $R2 = checkRelevance($H2);
6360 if($R1 and not $R2)
6361 { # libebook/e-book.h
6362 return -1;
6363 }
6364 elsif($R2 and not $R1)
6365 { # libebook/e-book.h
6366 return 1;
6367 }
6368 else
6369 {
6370 return (lc($H1) cmp lc($H2));
6371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006372 }
6373}
6374
6375sub searchForHeaders($)
6376{
6377 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006378
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006380 registerGccHeaders();
6381
6382 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6383 { # c++ standard include paths
6384 registerCppHeaders();
6385 }
6386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006387 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006388 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6389 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006390 {
6391 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006392 if($SystemRoot)
6393 {
6394 if(is_abs($Path)) {
6395 $Path = $SystemRoot.$Path;
6396 }
6397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006398 if(not -e $Path) {
6399 exitStatus("Access_Error", "can't access \'$Path\'");
6400 }
6401 elsif(-f $Path) {
6402 exitStatus("Access_Error", "\'$Path\' - not a directory");
6403 }
6404 elsif(-d $Path)
6405 {
6406 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006407 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006408 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6409 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006410 }
6411 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006412 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006413 }
6414 }
6415 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006416 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006417 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6418 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006420 # registering directories
6421 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6422 {
6423 next if(not -e $Path);
6424 $Path = get_abs_path($Path);
6425 $Path = path_format($Path, $OSgroup);
6426 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006427 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006428 }
6429 elsif(-f $Path)
6430 {
6431 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006432 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 and not $LocalIncludes{$Dir})
6434 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006435 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006436 # if(my $OutDir = get_dirname($Dir))
6437 # { # registering the outer directory
6438 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6439 # and not $LocalIncludes{$OutDir}) {
6440 # registerDir($OutDir, 0, $LibVersion);
6441 # }
6442 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006443 }
6444 }
6445 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006446
6447 # clean memory
6448 %RegisteredDirs = ();
6449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450 # registering headers
6451 my $Position = 0;
6452 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6453 {
6454 if(is_abs($Dest) and not -e $Dest) {
6455 exitStatus("Access_Error", "can't access \'$Dest\'");
6456 }
6457 $Dest = path_format($Dest, $OSgroup);
6458 if(is_header($Dest, 1, $LibVersion))
6459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006460 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006461 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6462 }
6463 }
6464 elsif(-d $Dest)
6465 {
6466 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006467 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006468 {
6469 next if(ignore_path($Path));
6470 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006471 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006472 push(@Registered, $HPath);
6473 }
6474 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006475 @Registered = sort {sortHeaders($a, $b)} @Registered;
6476 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006477 foreach my $Path (@Registered) {
6478 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6479 }
6480 }
6481 else {
6482 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6483 }
6484 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485
6486 if(defined $Tolerance and $Tolerance=~/4/)
6487 { # 4 - skip headers included by others
6488 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6489 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006490 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006491 delete($Registered_Headers{$LibVersion}{$Path});
6492 }
6493 }
6494 }
6495
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006496 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6497 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006498 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006499 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006500 if(is_abs($Header) and not -f $Header) {
6501 exitStatus("Access_Error", "can't access file \'$Header\'");
6502 }
6503 $Header = path_format($Header, $OSgroup);
6504 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6505 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006506 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006507 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006508 }
6509 else {
6510 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006512 }
6513 }
6514 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6515 { # set relative paths (for duplicates)
6516 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6517 { # search for duplicates
6518 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6519 my $Prefix = get_dirname($FirstPath);
6520 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6521 { # detect a shortest distinguishing prefix
6522 my $NewPrefix = $1;
6523 my %Identity = ();
6524 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6525 {
6526 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6527 $Identity{$Path} = $1;
6528 }
6529 }
6530 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006531 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6533 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6534 }
6535 last;
6536 }
6537 $Prefix = $NewPrefix; # increase prefix
6538 }
6539 }
6540 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006541
6542 # clean memory
6543 %HeaderName_Paths = ();
6544
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006545 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6546 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006547 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006548 my ($Pos, $PairPos) = (-1, -1);
6549 my ($Path, $PairPath) = ();
6550 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6551 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6552 foreach my $Header_Path (@Paths)
6553 {
6554 if(get_filename($Header_Path) eq $PairName)
6555 {
6556 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6557 $PairPath = $Header_Path;
6558 }
6559 if(get_filename($Header_Path) eq $HeaderName)
6560 {
6561 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6562 $Path = $Header_Path;
6563 }
6564 }
6565 if($PairPos!=-1 and $Pos!=-1
6566 and int($PairPos)<int($Pos))
6567 {
6568 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6569 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6570 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6571 }
6572 }
6573 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6574 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6575 }
6576}
6577
6578sub detect_real_includes($$)
6579{
6580 my ($AbsPath, $LibVersion) = @_;
6581 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6582 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6583 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6584 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6585 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006586 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6587
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006588 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6589 return () if(not $Path);
6590 open(PREPROC, $Path);
6591 while(<PREPROC>)
6592 {
6593 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6594 {
6595 my $Include = path_format($1, $OSgroup);
6596 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6597 next;
6598 }
6599 if($Include eq $AbsPath) {
6600 next;
6601 }
6602 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6603 }
6604 }
6605 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006606 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6607}
6608
6609sub detect_header_includes($$)
6610{
6611 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006612 return if(not $LibVersion or not $Path);
6613 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6614 return;
6615 }
6616 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6617
6618 if(not -e $Path) {
6619 return;
6620 }
6621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006622 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006623 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6624 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006625 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006626 {
6627 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006628 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006629 }
6630 if($RedirectPath ne $Path) {
6631 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6632 }
6633 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006634 else
6635 { # can't find
6636 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006638 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006639 if(my $Inc = parse_includes($Content, $Path))
6640 {
6641 foreach my $Include (keys(%{$Inc}))
6642 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006643 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006644
6645 if(defined $Tolerance and $Tolerance=~/4/)
6646 {
6647 if(my $HPath = identifyHeader($Include, $LibVersion))
6648 {
6649 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6650 }
6651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006654}
6655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006656sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006657{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658 my $Path = $_[0];
6659 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006660 if($OStarget eq "symbian")
6661 {
6662 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6663 { # epoc32/include/libc/{stdio, ...}.h
6664 return 1;
6665 }
6666 }
6667 else
6668 {
6669 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6670 { # /usr/include/{stdio, ...}.h
6671 return 1;
6672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006674 return 0;
6675}
6676
6677sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006678{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006679 my $Dir = $_[0];
6680 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006681 if($OStarget eq "symbian")
6682 {
6683 if(get_filename($OutDir) eq "libc"
6684 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6685 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6686 return 1;
6687 }
6688 }
6689 else
6690 { # linux
6691 if($OutDir eq "/usr/include"
6692 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6693 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6694 return 1;
6695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006696 }
6697 return 0;
6698}
6699
6700sub detect_recursive_includes($$)
6701{
6702 my ($AbsPath, $LibVersion) = @_;
6703 return () if(not $AbsPath);
6704 if(isCyclical(\@RecurInclude, $AbsPath)) {
6705 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6706 }
6707 my ($AbsDir, $Name) = separate_path($AbsPath);
6708 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006709 { # system GLIBC internals
6710 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006711 }
6712 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6713 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6714 }
6715 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006716
6717 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6718 { # skip /usr/include/c++/*/ headers
6719 return () if(not $ExtraInfo);
6720 }
6721
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006722 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006723 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006724 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 { # check "real" (non-"model") include paths
6726 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6727 pop(@RecurInclude);
6728 return @Paths;
6729 }
6730 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6731 detect_header_includes($AbsPath, $LibVersion);
6732 }
6733 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6734 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006735 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006737 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006738 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006739 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006740 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006741 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 }
6743 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006744 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006745 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006746 { # search for the nearest header
6747 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006748 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006749 if(-f $Candidate) {
6750 $HPath = $Candidate;
6751 }
6752 }
6753 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006754 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006755 }
6756 next if(not $HPath);
6757 if($HPath eq $AbsPath) {
6758 next;
6759 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006760
6761 if($Debug)
6762 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006763# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6764# {
6765# print STDERR "$AbsPath -> $HPath\n";
6766# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006767 }
6768
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006769 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6770 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006771 { # only include <...>, skip include "..." prefixes
6772 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6773 }
6774 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6775 {
6776 if($IncPath eq $AbsPath) {
6777 next;
6778 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006779 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6780 if($RIncType==-1)
6781 { # include "..."
6782 $RIncType = $IncType;
6783 }
6784 elsif($RIncType==2)
6785 {
6786 if($IncType!=-1) {
6787 $RIncType = $IncType;
6788 }
6789 }
6790 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006791 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6792 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6793 }
6794 }
6795 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6796 {
6797 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6798 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6799 { # distinguish math.h from glibc and math.h from the tested library
6800 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6801 last;
6802 }
6803 }
6804 }
6805 pop(@RecurInclude);
6806 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6807}
6808
6809sub find_in_framework($$$)
6810{
6811 my ($Header, $Framework, $LibVersion) = @_;
6812 return "" if(not $Header or not $Framework or not $LibVersion);
6813 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6814 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6815 }
6816 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6817 {
6818 if(get_filename($Dependency) eq $Framework
6819 and -f get_dirname($Dependency)."/".$Header) {
6820 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6821 }
6822 }
6823 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6824}
6825
6826sub find_in_defaults($)
6827{
6828 my $Header = $_[0];
6829 return "" if(not $Header);
6830 if(defined $Cache{"find_in_defaults"}{$Header}) {
6831 return $Cache{"find_in_defaults"}{$Header};
6832 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006833 foreach my $Dir (@DefaultIncPaths,
6834 @DefaultGccPaths,
6835 @DefaultCppPaths,
6836 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006837 {
6838 next if(not $Dir);
6839 if(-f $Dir."/".$Header) {
6840 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6841 }
6842 }
6843 return ($Cache{"find_in_defaults"}{$Header}="");
6844}
6845
6846sub cmp_paths($$)
6847{
6848 my ($Path1, $Path2) = @_;
6849 my @Parts1 = split(/[\/\\]/, $Path1);
6850 my @Parts2 = split(/[\/\\]/, $Path2);
6851 foreach my $Num (0 .. $#Parts1)
6852 {
6853 my $Part1 = $Parts1[$Num];
6854 my $Part2 = $Parts2[$Num];
6855 if($GlibcDir{$Part1}
6856 and not $GlibcDir{$Part2}) {
6857 return 1;
6858 }
6859 elsif($GlibcDir{$Part2}
6860 and not $GlibcDir{$Part1}) {
6861 return -1;
6862 }
6863 elsif($Part1=~/glib/
6864 and $Part2!~/glib/) {
6865 return 1;
6866 }
6867 elsif($Part1!~/glib/
6868 and $Part2=~/glib/) {
6869 return -1;
6870 }
6871 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6872 return $CmpRes;
6873 }
6874 }
6875 return 0;
6876}
6877
6878sub checkRelevance($)
6879{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006880 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006881 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006882
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006883 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006884 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006885 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006886
6887 my $Name = lc(get_filename($Path));
6888 my $Dir = lc(get_dirname($Path));
6889
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006890 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006891
6892 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006893 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006894 my $Len = length($Token);
6895 next if($Len<=1);
6896 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6897 { # include/evolution-data-server-1.4/libebook/e-book.h
6898 return 1;
6899 }
6900 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006901 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006902 return 1;
6903 }
6904 }
6905 return 0;
6906}
6907
6908sub checkFamily(@)
6909{
6910 my @Paths = @_;
6911 return 1 if($#Paths<=0);
6912 my %Prefix = ();
6913 foreach my $Path (@Paths)
6914 {
6915 if($SystemRoot) {
6916 $Path = cut_path_prefix($Path, $SystemRoot);
6917 }
6918 if(my $Dir = get_dirname($Path))
6919 {
6920 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6921 $Prefix{$Dir} += 1;
6922 $Prefix{get_dirname($Dir)} += 1;
6923 }
6924 }
6925 foreach (sort keys(%Prefix))
6926 {
6927 if(get_depth($_)>=3
6928 and $Prefix{$_}==$#Paths+1) {
6929 return 1;
6930 }
6931 }
6932 return 0;
6933}
6934
6935sub isAcceptable($$$)
6936{
6937 my ($Header, $Candidate, $LibVersion) = @_;
6938 my $HName = get_filename($Header);
6939 if(get_dirname($Header))
6940 { # with prefix
6941 return 1;
6942 }
6943 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6944 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6945 return 1;
6946 }
6947 if(checkRelevance($Candidate))
6948 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6949 return 1;
6950 }
6951 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6952 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6953 # /usr/include/qt4/Qt/qsslconfiguration.h
6954 return 1;
6955 }
6956 if($OStarget eq "symbian")
6957 {
6958 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6959 return 1;
6960 }
6961 }
6962 return 0;
6963}
6964
6965sub isRelevant($$$)
6966{ # disallow to search for "abstract" headers in too deep directories
6967 my ($Header, $Candidate, $LibVersion) = @_;
6968 my $HName = get_filename($Header);
6969 if($OStarget eq "symbian")
6970 {
6971 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6972 return 0;
6973 }
6974 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006975 if($OStarget ne "bsd")
6976 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006977 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6978 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6979 return 0;
6980 }
6981 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006982 if($OStarget ne "windows")
6983 {
6984 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6985 { # skip /usr/include/wine/msvcrt
6986 return 0;
6987 }
6988 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006989 if(not get_dirname($Header)
6990 and $Candidate=~/[\/\\]wx[\/\\]/)
6991 { # do NOT search in system /wx/ directory
6992 # for headers without a prefix: sstream.h
6993 return 0;
6994 }
6995 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6996 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6997 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6998 return 0;
6999 }
7000 if($Candidate=~/[\/\\]asm-/
7001 and (my $Arch = getArch($LibVersion)) ne "unknown")
7002 { # arch-specific header files
7003 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7004 {# skip ../asm-arm/ if using x86 architecture
7005 return 0;
7006 }
7007 }
7008 my @Candidates = getSystemHeaders($HName, $LibVersion);
7009 if($#Candidates==1)
7010 { # unique header
7011 return 1;
7012 }
7013 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7014 if($#SCandidates==1)
7015 { # unique name
7016 return 1;
7017 }
7018 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7019 if(get_depth($Candidate)-$SystemDepth>=5)
7020 { # abstract headers in too deep directories
7021 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7022 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7023 return 0;
7024 }
7025 }
7026 if($Header eq "parser.h"
7027 and $Candidate!~/\/libxml2\//)
7028 { # select parser.h from xml2 library
7029 return 0;
7030 }
7031 if(not get_dirname($Header)
7032 and keys(%{$SystemHeaders{$HName}})>=3)
7033 { # many headers with the same name
7034 # like thread.h included without a prefix
7035 if(not checkFamily(@Candidates)) {
7036 return 0;
7037 }
7038 }
7039 return 1;
7040}
7041
7042sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007043{ # cache function
7044 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7045 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7046 }
7047 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7048}
7049
7050sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007051{
7052 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007053 if(-f $Header) {
7054 return $Header;
7055 }
7056 if(is_abs($Header) and not -f $Header)
7057 { # incorrect absolute path
7058 return "";
7059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007060 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007061 { # too abstract configuration headers
7062 return "";
7063 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007064 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007065 if($OSgroup ne "windows")
7066 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007067 if(defined $WinHeaders{lc($HName)}
7068 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007069 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007070 return "";
7071 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007072 }
7073 if($OSgroup ne "macos")
7074 {
7075 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007076 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007077 return "";
7078 }
7079 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007080
7081 if(defined $ObsoleteHeaders{$HName})
7082 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007083 return "";
7084 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007085 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7086 {
7087 if(defined $AlienHeaders{$HName}
7088 or defined $AlienHeaders{$Header})
7089 { # alien headers from other systems
7090 return "";
7091 }
7092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007093
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007094 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007095 { # search in default paths
7096 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007097 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007098 }
7099 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007100 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007101 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007102 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007103 }
7104 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7105 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7106 {
7107 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007108 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007109 }
7110 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007111 # error
7112 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007113}
7114
7115sub getSystemHeaders($$)
7116{
7117 my ($Header, $LibVersion) = @_;
7118 my @Candidates = ();
7119 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7120 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007121 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007122 next;
7123 }
7124 push(@Candidates, $Candidate);
7125 }
7126 return @Candidates;
7127}
7128
7129sub cut_path_prefix($$)
7130{
7131 my ($Path, $Prefix) = @_;
7132 return $Path if(not $Prefix);
7133 $Prefix=~s/[\/\\]+\Z//;
7134 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7135 return $Path;
7136}
7137
7138sub is_default_include_dir($)
7139{
7140 my $Dir = $_[0];
7141 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007142 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007143}
7144
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007145sub identifyHeader($$)
7146{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007147 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007148 if(not $Header) {
7149 return "";
7150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007151 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007152 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7153 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007154 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007155 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007156}
7157
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007158sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159{ # search for header by absolute path, relative path or name
7160 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007161 if(-f $Header)
7162 { # it's relative or absolute path
7163 return get_abs_path($Header);
7164 }
7165 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7166 and my $HeaderDir = find_in_defaults($Header))
7167 { # search for libc headers in the /usr/include
7168 # for non-libc target library before searching
7169 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007170 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007171 }
7172 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7173 { # search in the target library paths
7174 return $Path;
7175 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007176 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007177 { # search in the internal GCC include paths
7178 return $DefaultGccHeader{$Header};
7179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007180 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007181 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007182 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007183 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007184 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185 { # search in the default G++ include paths
7186 return $DefaultCppHeader{$Header};
7187 }
7188 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7189 { # search everywhere in the system
7190 return $AnyPath;
7191 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007192 elsif($OSgroup eq "macos")
7193 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7194 if(my $Dir = get_dirname($Header))
7195 {
7196 my $RelPath = "Headers\/".get_filename($Header);
7197 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007198 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007199 }
7200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007202 # cannot find anything
7203 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204}
7205
7206sub getLocation($)
7207{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007208 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7209 {
7210 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007211 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007213 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007214 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007215}
7216
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217sub getNameByInfo($)
7218{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007219 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007220 {
7221 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7222 {
7223 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7224 {
7225 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7226 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007227 my $Str = $1;
7228 if($CppMode{$Version}
7229 and $Str=~/\Ac99_(.+)\Z/)
7230 {
7231 if($CppKeywords_A{$1}) {
7232 $Str=$1;
7233 }
7234 }
7235 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007236 }
7237 }
7238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007240 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007241}
7242
7243sub getTreeStr($)
7244{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007245 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007246 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007247 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7248 {
7249 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007250 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007251 and $Str=~/\Ac99_(.+)\Z/)
7252 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007253 if($CppKeywords_A{$1}) {
7254 $Str=$1;
7255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007256 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007257 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007260 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007261}
7262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263sub getFuncShortName($)
7264{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007265 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007266 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007267 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007268 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007269 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007270 {
7271 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7272 {
7273 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7274 return "operator ".$RName;
7275 }
7276 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007277 }
7278 else
7279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007280 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7281 {
7282 if(my $Ind = $Operator_Indication{$1}) {
7283 return "operator".$Ind;
7284 }
7285 elsif(not $UnknownOperator{$1})
7286 {
7287 printMsg("WARNING", "unknown operator $1");
7288 $UnknownOperator{$1} = 1;
7289 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007290 }
7291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007292 }
7293 else
7294 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007295 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7296 return getTreeStr($1);
7297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007298 }
7299 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007300 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007301}
7302
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007303sub getFuncReturn($)
7304{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007305 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7306 {
7307 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7308 {
7309 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7310 return $1;
7311 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007312 }
7313 }
7314 return "";
7315}
7316
7317sub getFuncOrig($)
7318{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007319 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7320 {
7321 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7322 return $1;
7323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007324 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007325 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007326}
7327
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007328sub unmangleArray(@)
7329{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007330 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 { # MSVC mangling
7332 my $UndNameCmd = get_CmdPath("undname");
7333 if(not $UndNameCmd) {
7334 exitStatus("Not_Found", "can't find \"undname\"");
7335 }
7336 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007337 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007338 }
7339 else
7340 { # GCC mangling
7341 my $CppFiltCmd = get_CmdPath("c++filt");
7342 if(not $CppFiltCmd) {
7343 exitStatus("Not_Found", "can't find c++filt in PATH");
7344 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007345 if(not defined $CPPFILT_SUPPORT_FILE)
7346 {
7347 my $Info = `$CppFiltCmd -h 2>&1`;
7348 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7349 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007350 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007351 if($CPPFILT_SUPPORT_FILE)
7352 { # new versions of c++filt can take a file
7353 if($#_>$MAX_CPPFILT_FILE_SIZE)
7354 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7355 # this is fixed in the oncoming version of Binutils
7356 my @Half = splice(@_, 0, ($#_+1)/2);
7357 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007358 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007359 else
7360 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007361 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7362 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7363 if($?==139)
7364 { # segmentation fault
7365 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7366 }
7367 return split(/\n/, $Res);
7368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007369 }
7370 else
7371 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007372 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7373 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007374 my @Half = splice(@_, 0, ($#_+1)/2);
7375 return (unmangleArray(@Half), unmangleArray(@_))
7376 }
7377 else
7378 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007380 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7381 if($?==139)
7382 { # segmentation fault
7383 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7384 }
7385 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007386 }
7387 }
7388 }
7389}
7390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391sub get_ChargeLevel($$)
7392{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007393 my ($Symbol, $LibVersion) = @_;
7394 return "" if($Symbol!~/\A(_Z|\?)/);
7395 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7396 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007398 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007400 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 return "[in-charge]";
7402 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007403 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404 return "[not-in-charge]";
7405 }
7406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007407 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007408 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[in-charge]";
7411 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007412 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 return "[not-in-charge]";
7414 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007415 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 return "[in-charge-deleting]";
7417 }
7418 }
7419 }
7420 else
7421 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007422 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007423 return "[in-charge]";
7424 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007425 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007426 return "[not-in-charge]";
7427 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007428 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007429 return "[in-charge]";
7430 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007431 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007432 return "[not-in-charge]";
7433 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007434 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435 return "[in-charge-deleting]";
7436 }
7437 }
7438 return "";
7439}
7440
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007441sub get_Signature_M($$)
7442{
7443 my ($Symbol, $LibVersion) = @_;
7444 my $Signature_M = $tr_name{$Symbol};
7445 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7446 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007447 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007448 }
7449 return $Signature_M;
7450}
7451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452sub get_Signature($$)
7453{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007454 my ($Symbol, $LibVersion) = @_;
7455 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7456 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007458 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007459 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007460
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007461 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007463 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007464 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007465 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7466 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007467 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7468 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007469
7470 if(index($Symbol, "_ZTV")==0) {
7471 return "vtable for $ClassName [data]";
7472 }
7473
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007474 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007475 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7476 $Signature .= "~";
7477 }
7478 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007479 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007480 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007481 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007482 }
7483 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007484 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007485 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007486 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7487 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007489 else
7490 {
7491 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007492 }
7493 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007494 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007495 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007496 if($Pos eq "") {
7497 next;
7498 }
7499
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007500 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007501 if(not $ParamTypeId) {
7502 next;
7503 }
7504
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 if(not $ParamTypeName) {
7507 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7508 }
7509 foreach my $Typedef (keys(%ChangedTypedef))
7510 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007511 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7512 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7513 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007515 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7516 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007517 if($ParamName eq "this"
7518 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007519 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007520 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007521 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007522 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
7524 else {
7525 push(@ParamArray, $ParamTypeName);
7526 }
7527 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007528 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7529 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007530 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007531 }
7532 else
7533 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007534 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007535 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007536 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007537 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007538 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007539 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7540 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007541 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007542 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7544 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007545 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007547 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7548 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007549 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007550 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007551 }
7552 }
7553 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007554 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007555 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007556 }
7557 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007558 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007559 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007560 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561}
7562
7563sub create_member_decl($$)
7564{
7565 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007566 if($TName=~/\([\*]+\)/)
7567 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007568 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7569 return $TName;
7570 }
7571 else
7572 {
7573 my @ArraySizes = ();
7574 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7575 push(@ArraySizes, $1);
7576 }
7577 return $TName." ".$Member.join("", @ArraySizes);
7578 }
7579}
7580
7581sub getFuncType($)
7582{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007583 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7584 {
7585 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7586 {
7587 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7588 {
7589 if($Type eq "method_type") {
7590 return "Method";
7591 }
7592 elsif($Type eq "function_type") {
7593 return "Function";
7594 }
7595 else {
7596 return "Other";
7597 }
7598 }
7599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007600 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007601 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007602}
7603
7604sub getFuncTypeId($)
7605{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007606 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7607 {
7608 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7609 return $1;
7610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007611 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007612 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613}
7614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007615sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007616{ # "._N" or "$_N" in older GCC versions
7617 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618}
7619
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007620sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007621{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007622 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7623 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007624 }
7625
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007626 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007627
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007628 if($_[1] ne "S")
7629 {
7630 $N=~s/\A[ ]+//g;
7631 $N=~s/[ ]+\Z//g;
7632 $N=~s/[ ]{2,}/ /g;
7633 }
7634
7635 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007636
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007637 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7638
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007639 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007640
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007641 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7642 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007643
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007644 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007645
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007646 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007647
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007648 if($_[1] eq "S")
7649 {
7650 if(index($N, "operator")!=-1) {
7651 $N=~s/\b(operator[ ]*)> >/$1>>/;
7652 }
7653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007654
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007655 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007656
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007657 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007658}
7659
7660sub get_HeaderDeps($$)
7661{
7662 my ($AbsPath, $LibVersion) = @_;
7663 return () if(not $AbsPath or not $LibVersion);
7664 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7665 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7666 }
7667 my %IncDir = ();
7668 detect_recursive_includes($AbsPath, $LibVersion);
7669 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7670 {
7671 next if(not $HeaderPath);
7672 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7673 my $Dir = get_dirname($HeaderPath);
7674 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7675 {
7676 my $Dep = $Dir;
7677 if($Prefix)
7678 {
7679 if($OSgroup eq "windows")
7680 { # case insensitive seach on windows
7681 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7682 next;
7683 }
7684 }
7685 elsif($OSgroup eq "macos")
7686 { # seach in frameworks
7687 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7688 {
7689 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7690 {# frameworks
7691 my ($HFramework, $HName) = ($1, $2);
7692 $Dep = $HFramework;
7693 }
7694 else
7695 {# mismatch
7696 next;
7697 }
7698 }
7699 }
7700 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7701 { # Linux, FreeBSD
7702 next;
7703 }
7704 }
7705 if(not $Dep)
7706 { # nothing to include
7707 next;
7708 }
7709 if(is_default_include_dir($Dep))
7710 { # included by the compiler
7711 next;
7712 }
7713 if(get_depth($Dep)==1)
7714 { # too short
7715 next;
7716 }
7717 if(isLibcDir($Dep))
7718 { # do NOT include /usr/include/{sys,bits}
7719 next;
7720 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007721 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007722 }
7723 }
7724 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7725 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7726}
7727
7728sub sortIncPaths($$)
7729{
7730 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007731 if(not $ArrRef or $#{$ArrRef}<0) {
7732 return $ArrRef;
7733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007734 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7735 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007736 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007737 return $ArrRef;
7738}
7739
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007740sub sortDeps($$$)
7741{
7742 if($Header_Dependency{$_[2]}{$_[0]}
7743 and not $Header_Dependency{$_[2]}{$_[1]}) {
7744 return 1;
7745 }
7746 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7747 and $Header_Dependency{$_[2]}{$_[1]}) {
7748 return -1;
7749 }
7750 return 0;
7751}
7752
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007753sub join_P($$)
7754{
7755 my $S = "/";
7756 if($OSgroup eq "windows") {
7757 $S = "\\";
7758 }
7759 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007760}
7761
7762sub get_namespace_additions($)
7763{
7764 my $NameSpaces = $_[0];
7765 my ($Additions, $AddNameSpaceId) = ("", 1);
7766 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7767 {
7768 next if($SkipNameSpaces{$Version}{$NS});
7769 next if(not $NS or $NameSpaces->{$NS}==-1);
7770 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7771 next if($NS=~/\A__/i);
7772 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007773 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007774 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7775 my @NS_Parts = split(/::/, $NS);
7776 next if($#NS_Parts==-1);
7777 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7778 foreach my $NS_Part (@NS_Parts)
7779 {
7780 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7781 $TypeDecl_Suffix .= "}";
7782 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007783 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7785 $Additions.=" $TypeDecl\n $FuncDecl\n";
7786 $AddNameSpaceId+=1;
7787 }
7788 return $Additions;
7789}
7790
7791sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007792{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007793 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007794 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007795 if($Fmt eq "windows")
7796 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007797 $Path=~s/\//\\/g;
7798 $Path=lc($Path);
7799 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007800 else
7801 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007802 $Path=~s/\\/\//g;
7803 }
7804 return $Path;
7805}
7806
7807sub inc_opt($$)
7808{
7809 my ($Path, $Style) = @_;
7810 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007811 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007812 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007813 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007814 return "-I\"".path_format($Path, "unix")."\"";
7815 }
7816 elsif($OSgroup eq "macos"
7817 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007818 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007819 return "-F".esc(get_dirname($Path));
7820 }
7821 else {
7822 return "-I".esc($Path);
7823 }
7824 }
7825 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007826 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007827 }
7828 return "";
7829}
7830
7831sub platformSpecs($)
7832{
7833 my $LibVersion = $_[0];
7834 my $Arch = getArch($LibVersion);
7835 if($OStarget eq "symbian")
7836 { # options for GCCE compiler
7837 my %Symbian_Opts = map {$_=>1} (
7838 "-D__GCCE__",
7839 "-DUNICODE",
7840 "-fexceptions",
7841 "-D__SYMBIAN32__",
7842 "-D__MARM_INTERWORK__",
7843 "-D_UNICODE",
7844 "-D__S60_50__",
7845 "-D__S60_3X__",
7846 "-D__SERIES60_3X__",
7847 "-D__EPOC32__",
7848 "-D__MARM__",
7849 "-D__EABI__",
7850 "-D__MARM_ARMV5__",
7851 "-D__SUPPORT_CPP_EXCEPTIONS__",
7852 "-march=armv5t",
7853 "-mapcs",
7854 "-mthumb-interwork",
7855 "-DEKA2",
7856 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7857 );
7858 return join(" ", keys(%Symbian_Opts));
7859 }
7860 elsif($OSgroup eq "windows"
7861 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7862 { # add options to MinGW compiler
7863 # to simulate the MSVC compiler
7864 my %MinGW_Opts = map {$_=>1} (
7865 "-D_WIN32",
7866 "-D_STDCALL_SUPPORTED",
7867 "-D__int64=\"long long\"",
7868 "-D__int32=int",
7869 "-D__int16=short",
7870 "-D__int8=char",
7871 "-D__possibly_notnullterminated=\" \"",
7872 "-D__nullterminated=\" \"",
7873 "-D__nullnullterminated=\" \"",
7874 "-D__w64=\" \"",
7875 "-D__ptr32=\" \"",
7876 "-D__ptr64=\" \"",
7877 "-D__forceinline=inline",
7878 "-D__inline=inline",
7879 "-D__uuidof(x)=IID()",
7880 "-D__try=",
7881 "-D__except(x)=",
7882 "-D__declspec(x)=__attribute__((x))",
7883 "-D__pragma(x)=",
7884 "-D_inline=inline",
7885 "-D__forceinline=__inline",
7886 "-D__stdcall=__attribute__((__stdcall__))",
7887 "-D__cdecl=__attribute__((__cdecl__))",
7888 "-D__fastcall=__attribute__((__fastcall__))",
7889 "-D__thiscall=__attribute__((__thiscall__))",
7890 "-D_stdcall=__attribute__((__stdcall__))",
7891 "-D_cdecl=__attribute__((__cdecl__))",
7892 "-D_fastcall=__attribute__((__fastcall__))",
7893 "-D_thiscall=__attribute__((__thiscall__))",
7894 "-DSHSTDAPI_(x)=x",
7895 "-D_MSC_EXTENSIONS",
7896 "-DSECURITY_WIN32",
7897 "-D_MSC_VER=1500",
7898 "-D_USE_DECLSPECS_FOR_SAL",
7899 "-D__noop=\" \"",
7900 "-DDECLSPEC_DEPRECATED=\" \"",
7901 "-D__builtin_alignof(x)=__alignof__(x)",
7902 "-DSORTPP_PASS");
7903 if($Arch eq "x86") {
7904 $MinGW_Opts{"-D_M_IX86=300"}=1;
7905 }
7906 elsif($Arch eq "x86_64") {
7907 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7908 }
7909 elsif($Arch eq "ia64") {
7910 $MinGW_Opts{"-D_M_IA64=300"}=1;
7911 }
7912 return join(" ", keys(%MinGW_Opts));
7913 }
7914 return "";
7915}
7916
7917my %C_Structure = map {$_=>1} (
7918# FIXME: Can't separate union and struct data types before dumping,
7919# so it sometimes cause compilation errors for unknown reason
7920# when trying to declare TYPE* tmp_add_class_N
7921# This is a list of such structures + list of other C structures
7922 "sigval",
7923 "sigevent",
7924 "sigaction",
7925 "sigvec",
7926 "sigstack",
7927 "timeval",
7928 "timezone",
7929 "rusage",
7930 "rlimit",
7931 "wait",
7932 "flock",
7933 "stat",
7934 "_stat",
7935 "stat32",
7936 "_stat32",
7937 "stat64",
7938 "_stat64",
7939 "_stati64",
7940 "if_nameindex",
7941 "usb_device",
7942 "sigaltstack",
7943 "sysinfo",
7944 "timeLocale",
7945 "tcp_debug",
7946 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007947 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007948 "timespec",
7949 "random_data",
7950 "drand48_data",
7951 "_IO_marker",
7952 "_IO_FILE",
7953 "lconv",
7954 "sched_param",
7955 "tm",
7956 "itimerspec",
7957 "_pthread_cleanup_buffer",
7958 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007959 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007960 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007961 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007962 "sigcontext",
7963 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007964 # Mac
7965 "_timex",
7966 "_class_t",
7967 "_category_t",
7968 "_class_ro_t",
7969 "_protocol_t",
7970 "_message_ref_t",
7971 "_super_message_ref_t",
7972 "_ivar_t",
7973 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007974);
7975
7976sub getCompileCmd($$$)
7977{
7978 my ($Path, $Opt, $Inc) = @_;
7979 my $GccCall = $GCC_PATH;
7980 if($Opt) {
7981 $GccCall .= " ".$Opt;
7982 }
7983 $GccCall .= " -x ";
7984 if($OSgroup eq "macos") {
7985 $GccCall .= "objective-";
7986 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007987
7988 if($EMERGENCY_MODE_48)
7989 { # workaround for GCC 4.8 (C only)
7990 $GccCall .= "c++";
7991 }
7992 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993 { # compile as "C++" header
7994 # to obtain complete dump using GCC 4.0
7995 $GccCall .= "c++-header";
7996 }
7997 else
7998 { # compile as "C++" source
7999 # GCC 3.3 cannot compile headers
8000 $GccCall .= "c++";
8001 }
8002 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008003 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008004 $GccCall .= " ".$Opts;
8005 }
8006 # allow extra qualifications
8007 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008008 $GccCall .= " -fpermissive";
8009 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008010 if($NoStdInc)
8011 {
8012 $GccCall .= " -nostdinc";
8013 $GccCall .= " -nostdinc++";
8014 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008015 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008016 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008017 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008018 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008019 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008020 if($Inc)
8021 { # include paths
8022 $GccCall .= " ".$Inc;
8023 }
8024 return $GccCall;
8025}
8026
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008027sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008028{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008029 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008030 my %HeaderElems = (
8031 # Types
8032 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008033 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008034 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8035 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008036 "time.h" => ["time_t"],
8037 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008038 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8039 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008040 "stdbool.h" => ["_Bool"],
8041 "rpc/xdr.h" => ["bool_t"],
8042 "in_systm.h" => ["n_long", "n_short"],
8043 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008044 "arpa/inet.h" => ["fw_src", "ip_src"],
8045 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008046 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008047 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008048 );
8049 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008050 foreach (keys(%HeaderElems))
8051 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008052 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008053 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008054 }
8055 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008056 my %Types = ();
8057 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8058 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008059 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008060 }
8061 if(keys(%Types))
8062 {
8063 my %AddHeaders = ();
8064 foreach my $Type (keys(%Types))
8065 {
8066 if(my $Header = $AutoPreamble{$Type})
8067 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008068 if(my $Path = identifyHeader($Header, $LibVersion))
8069 {
8070 if(skipHeader($Path, $LibVersion)) {
8071 next;
8072 }
8073 $Path = path_format($Path, $OSgroup);
8074 $AddHeaders{$Path}{"Type"} = $Type;
8075 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008076 }
8077 }
8078 }
8079 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008080 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008081 }
8082 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008083 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008084}
8085
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008086sub checkCTags($)
8087{
8088 my $Path = $_[0];
8089 if(not $Path) {
8090 return;
8091 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008092 my $CTags = undef;
8093
8094 if($OSgroup eq "bsd")
8095 { # use ectags on BSD
8096 $CTags = get_CmdPath("ectags");
8097 if(not $CTags) {
8098 printMsg("WARNING", "can't find \'ectags\' program");
8099 }
8100 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008101 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008102 $CTags = get_CmdPath("ctags");
8103 }
8104 if(not $CTags)
8105 {
8106 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008107 return;
8108 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008109
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008110 if($OSgroup ne "linux")
8111 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008112 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8113 if($Info!~/exuberant/i)
8114 {
8115 printMsg("WARNING", "incompatible version of \'ctags\' program");
8116 return;
8117 }
8118 }
8119
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008120 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008121 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008122 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008123 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008124 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008125 open(CTAGS, "<", $Out);
8126 while(my $Line = <CTAGS>)
8127 {
8128 chomp($Line);
8129 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008130 if(defined $Intrinsic_Keywords{$Name})
8131 { # noise
8132 next;
8133 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008134 if($Type eq "n")
8135 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008136 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008137 next;
8138 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008139 if(index($Scpe, "struct:")==0) {
8140 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008141 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008142 if(index($Scpe, "namespace:")==0)
8143 {
8144 if($Scpe=~s/\Anamespace://) {
8145 $Name = $Scpe."::".$Name;
8146 }
8147 }
8148 $TUnit_NameSpaces{$Version}{$Name} = 1;
8149 }
8150 elsif($Type eq "p")
8151 {
8152 if(not $Scpe or index($Scpe, "namespace:")==0) {
8153 $TUnit_Funcs{$Version}{$Name} = 1;
8154 }
8155 }
8156 elsif($Type eq "x")
8157 {
8158 if(not $Scpe or index($Scpe, "namespace:")==0) {
8159 $TUnit_Vars{$Version}{$Name} = 1;
8160 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008161 }
8162 }
8163 close(CTAGS);
8164}
8165
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008166sub preChange($$)
8167{
8168 my ($HeaderPath, $IncStr) = @_;
8169
8170 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8171 my $Content = undef;
8172
8173 if($OStarget eq "windows"
8174 and get_dumpmachine($GCC_PATH)=~/mingw/i
8175 and $MinGWMode{$Version}!=-1)
8176 { # modify headers to compile by MinGW
8177 if(not $Content)
8178 { # preprocessing
8179 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8180 }
8181 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8182 { # __asm { ... }
8183 $MinGWMode{$Version}=1;
8184 }
8185 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8186 { # comments after preprocessing
8187 $MinGWMode{$Version}=1;
8188 }
8189 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8190 { # 0xffui8
8191 $MinGWMode{$Version}=1;
8192 }
8193
8194 if($MinGWMode{$Version}) {
8195 printMsg("INFO", "Using MinGW compatibility mode");
8196 }
8197 }
8198
8199 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8200 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8201 { # rename C++ keywords in C code
8202 # disable this code by -cpp-compatible option
8203 if(not $Content)
8204 { # preprocessing
8205 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8206 }
8207 my $RegExp_C = join("|", keys(%CppKeywords_C));
8208 my $RegExp_F = join("|", keys(%CppKeywords_F));
8209 my $RegExp_O = join("|", keys(%CppKeywords_O));
8210
8211 my $Detected = undef;
8212
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008213 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 +04008214 { # MATCH:
8215 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008216 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008217 # unsigned private: 8;
8218 # DO NOT MATCH:
8219 # #pragma GCC visibility push(default)
8220 $CppMode{$Version} = 1;
8221 $Detected = "$1$2$3$4" if(not defined $Detected);
8222 }
8223 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8224 { # MATCH:
8225 # int delete(...);
8226 # int explicit(...);
8227 # DO NOT MATCH:
8228 # void operator delete(...)
8229 $CppMode{$Version} = 1;
8230 $Detected = "$1$2$3" if(not defined $Detected);
8231 }
8232 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8233 { # MATCH:
8234 # int bool;
8235 # DO NOT MATCH:
8236 # bool X;
8237 # return *this;
8238 # throw;
8239 $CppMode{$Version} = 1;
8240 $Detected = "$1$2$3" if(not defined $Detected);
8241 }
8242 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8243 { # MATCH:
8244 # int operator(...);
8245 # DO NOT MATCH:
8246 # int operator()(...);
8247 $CppMode{$Version} = 1;
8248 $Detected = "$1$2$3" if(not defined $Detected);
8249 }
8250 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8251 { # MATCH:
8252 # int foo(int operator);
8253 # int foo(int operator, int other);
8254 # DO NOT MATCH:
8255 # int operator,(...);
8256 $CppMode{$Version} = 1;
8257 $Detected = "$1$2$3" if(not defined $Detected);
8258 }
8259 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8260 { # MATCH:
8261 # int foo(gboolean *bool);
8262 # DO NOT MATCH:
8263 # void setTabEnabled(int index, bool);
8264 $CppMode{$Version} = 1;
8265 $Detected = "$1$2$3" if(not defined $Detected);
8266 }
8267 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8268 { # MATCH:
8269 # int foo(int* this);
8270 # int bar(int this);
8271 # int baz(int throw);
8272 # DO NOT MATCH:
8273 # foo(X, this);
8274 $CppMode{$Version} = 1;
8275 $Detected = "$1$2$3$4" if(not defined $Detected);
8276 }
8277 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8278 { # MATCH:
8279 # struct template {...};
8280 # extern template foo(...);
8281 $CppMode{$Version} = 1;
8282 $Detected = "$1$2" if(not defined $Detected);
8283 }
8284
8285 if($CppMode{$Version} == 1)
8286 {
8287 if($Debug)
8288 {
8289 $Detected=~s/\A\s+//g;
8290 printMsg("INFO", "Detected code: \"$Detected\"");
8291 }
8292 }
8293
8294 # remove typedef enum NAME NAME;
8295 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8296 my $N = 0;
8297 while($N<=$#FwdTypedefs-1)
8298 {
8299 my $S = $FwdTypedefs[$N];
8300 if($S eq $FwdTypedefs[$N+1])
8301 {
8302 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008303 $CppMode{$Version} = 1;
8304
8305 if($Debug) {
8306 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8307 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008308 }
8309 $N+=2;
8310 }
8311
8312 if($CppMode{$Version}==1) {
8313 printMsg("INFO", "Using C++ compatibility mode");
8314 }
8315 }
8316
8317 if($CppMode{$Version}==1
8318 or $MinGWMode{$Version}==1)
8319 {
8320 my $IPath = $TMP_DIR."/dump$Version.i";
8321 writeFile($IPath, $Content);
8322 return $IPath;
8323 }
8324
8325 return undef;
8326}
8327
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008328sub getDump()
8329{
8330 if(not $GCC_PATH) {
8331 exitStatus("Error", "internal error - GCC path is not set");
8332 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008333
8334 my @Headers = keys(%{$Registered_Headers{$Version}});
8335 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8336
8337 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8338
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008339 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008340 my $HeaderPath = $TmpHeaderPath;
8341
8342 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008343 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008344 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8345 {
8346 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008347 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008348 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008349 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008350 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8351 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008352 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008353 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008354 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008355 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8356 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008358 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008359 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008360
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008361 if($ExtraInfo)
8362 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008363 if($IncludeString) {
8364 writeFile($ExtraInfo."/include-string", $IncludeString);
8365 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008366 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8367 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008368
8369 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8370 {
8371 my $REDIR = "";
8372 foreach my $P1 (sort @Redirects) {
8373 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8374 }
8375 writeFile($ExtraInfo."/include-redirect", $REDIR);
8376 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008377 }
8378
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008379 if(not keys(%{$TargetHeaders{$Version}}))
8380 { # Target headers
8381 addTargetHeaders($Version);
8382 }
8383
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008384 # clean memory
8385 %RecursiveIncludes = ();
8386 %Header_Include_Prefix = ();
8387 %Header_Includes = ();
8388
8389 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008390 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008391 delete($Cache{"detect_header_includes"});
8392 delete($Cache{"selectSystemHeader"});
8393
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008394 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008395 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8396 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008397
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008398 if($ExtraInfo)
8399 { # extra information for other tools
8400 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8401 }
8402
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008403 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008404 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008405 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008406
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008407 if($COMMON_LANGUAGE{$Version} eq "C++") {
8408 checkCTags($Pre);
8409 }
8410
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008411 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8412 { # try to correct the preprocessor output
8413 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008414 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008416 if($COMMON_LANGUAGE{$Version} eq "C++")
8417 { # add classes and namespaces to the dump
8418 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008419 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008420 or $MinGWMode{$Version}==1) {
8421 $CHdump .= " -fpreprocessed";
8422 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008423 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008424 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008425 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008426 chdir($ORIG_DIR);
8427 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8428 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008429 my $Content = readFile($ClassDump);
8430 foreach my $ClassInfo (split(/\n\n/, $Content))
8431 {
8432 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8433 {
8434 my $CName = $1;
8435 next if($CName=~/\A(__|_objc_|_opaque_)/);
8436 $TUnit_NameSpaces{$Version}{$CName} = -1;
8437 if($CName=~/\A[\w:]+\Z/)
8438 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008439 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008440 }
8441 if($CName=~/(\w[\w:]*)::/)
8442 { # namespaces
8443 my $NS = $1;
8444 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8445 $TUnit_NameSpaces{$Version}{$NS} = 1;
8446 }
8447 }
8448 }
8449 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8450 { # read v-tables (advanced approach)
8451 my ($CName, $VTable) = ($1, $2);
8452 $ClassVTable_Content{$Version}{$CName} = $VTable;
8453 }
8454 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008455 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8456 { # add user-defined namespaces
8457 $TUnit_NameSpaces{$Version}{$NS} = 1;
8458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008459 if($Debug)
8460 { # debug mode
8461 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008462 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008463 }
8464 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008465 }
8466
8467 # add namespaces and classes
8468 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8469 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008470 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008471 }
8472 # some GCC versions don't include class methods to the TU dump by default
8473 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008474 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008475 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8476 {
8477 next if($C_Structure{$CName});
8478 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008479 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008480 if(not $Force and $GCC_44
8481 and $OSgroup eq "linux")
8482 { # optimization for linux with GCC >= 4.4
8483 # disable this code by -force option
8484 if(index($CName, "::")!=-1)
8485 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008486 next;
8487 }
8488 }
8489 else
8490 {
8491 if($CName=~/\A(.+)::[^:]+\Z/
8492 and $TUnit_Classes{$Version}{$1})
8493 { # classes inside other classes
8494 next;
8495 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008496 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008497 if(defined $TUnit_Funcs{$Version}{$CName})
8498 { # the same name for a function and type
8499 next;
8500 }
8501 if(defined $TUnit_Vars{$Version}{$CName})
8502 { # the same name for a variable and type
8503 next;
8504 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008505 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8506 }
8507 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008508 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008509 }
8510 }
8511 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8512 # create TU dump
8513 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008514 if($UserLang eq "C") {
8515 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8516 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008517 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 or $MinGWMode{$Version}==1) {
8519 $TUdump .= " -fpreprocessed";
8520 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008521 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008522 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8523 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008524 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008525 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008526 if($?)
8527 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008528 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008529 { # try to recompile
8530 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008531 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008532 and index($Errors, "c99_")!=-1
8533 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008534 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008535 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008536
8537 if($Debug)
8538 {
8539 # printMsg("INFO", $Errors);
8540 }
8541
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008542 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008543 resetLogging($Version);
8544 $TMP_DIR = tempdir(CLEANUP=>1);
8545 return getDump();
8546 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008547 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008548 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008549 { # add auto preamble headers and try again
8550 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008551 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008552 foreach my $Num (0 .. $#Headers)
8553 {
8554 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008555 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8556 {
8557 push_U($Include_Preamble{$Version}, $Path);
8558 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008559 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008560 }
8561 resetLogging($Version);
8562 $TMP_DIR = tempdir(CLEANUP=>1);
8563 return getDump();
8564 }
8565 elsif($Cpp0xMode{$Version}!=-1
8566 and ($Errors=~/\Q-std=c++0x\E/
8567 or $Errors=~/is not a class or namespace/))
8568 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008569 if(check_gcc($GCC_PATH, "4.6"))
8570 {
8571 $Cpp0xMode{$Version}=-1;
8572 printMsg("INFO", "Enabling c++0x mode");
8573 resetLogging($Version);
8574 $TMP_DIR = tempdir(CLEANUP=>1);
8575 $CompilerOptions{$Version} .= " -std=c++0x";
8576 return getDump();
8577 }
8578 else {
8579 printMsg("WARNING", "Probably c++0x construction detected");
8580 }
8581
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008582 }
8583 elsif($MinGWMode{$Version}==1)
8584 { # disable MinGW mode and try again
8585 $MinGWMode{$Version}=-1;
8586 resetLogging($Version);
8587 $TMP_DIR = tempdir(CLEANUP=>1);
8588 return getDump();
8589 }
8590 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008591 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008592 else {
8593 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 printMsg("ERROR", "some errors occurred when compiling headers");
8596 printErrorLog($Version);
8597 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008598 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008599 }
8600 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008601 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008602 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008603
8604 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8605 return $TUs[0];
8606 }
8607 else
8608 {
8609 my $Msg = "can't compile header(s)";
8610 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8611 $Msg .= "\nDid you install G++?";
8612 }
8613 exitStatus("Cannot_Compile", $Msg);
8614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008615}
8616
8617sub cmd_file($)
8618{
8619 my $Path = $_[0];
8620 return "" if(not $Path or not -e $Path);
8621 if(my $CmdPath = get_CmdPath("file")) {
8622 return `$CmdPath -b \"$Path\"`;
8623 }
8624 return "";
8625}
8626
8627sub getIncString($$)
8628{
8629 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008630 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008631 my $String = "";
8632 foreach (@{$ArrRef}) {
8633 $String .= " ".inc_opt($_, $Style);
8634 }
8635 return $String;
8636}
8637
8638sub getIncPaths(@)
8639{
8640 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008641 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008642 if($INC_PATH_AUTODETECT{$Version})
8643 { # auto-detecting dependencies
8644 my %Includes = ();
8645 foreach my $HPath (@HeaderPaths)
8646 {
8647 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8648 {
8649 if($Skip_Include_Paths{$Version}{$Dir}) {
8650 next;
8651 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008652 if($SystemRoot)
8653 {
8654 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8655 next;
8656 }
8657 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008658 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008659 }
8660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008662 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663 }
8664 }
8665 else
8666 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008667 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008668 }
8669 return \@IncPaths;
8670}
8671
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008672sub push_U($@)
8673{ # push unique
8674 if(my $Array = shift @_)
8675 {
8676 if(@_)
8677 {
8678 my %Exist = map {$_=>1} @{$Array};
8679 foreach my $Elem (@_)
8680 {
8681 if(not defined $Exist{$Elem})
8682 {
8683 push(@{$Array}, $Elem);
8684 $Exist{$Elem} = 1;
8685 }
8686 }
8687 }
8688 }
8689}
8690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691sub callPreprocessor($$$)
8692{
8693 my ($Path, $Inc, $LibVersion) = @_;
8694 return "" if(not $Path or not -f $Path);
8695 my $IncludeString=$Inc;
8696 if(not $Inc) {
8697 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8698 }
8699 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008700 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008701 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008702 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008703}
8704
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008705sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008706{ # native "find" is much faster than File::Find (~6x)
8707 # also the File::Find doesn't support --maxdepth N option
8708 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008709 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 return () if(not $Path or not -e $Path);
8711 if($OSgroup eq "windows")
8712 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008713 $Path = get_abs_path($Path);
8714 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008715 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008716 if($MaxDepth!=1) {
8717 $Cmd .= " /S";
8718 }
8719 if($Type eq "d") {
8720 $Cmd .= " /AD";
8721 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008722 elsif($Type eq "f") {
8723 $Cmd .= " /A-D";
8724 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008725 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008726 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008727 {
8728 if(not $UseRegex)
8729 { # FIXME: how to search file names in MS shell?
8730 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008731 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008732 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008733 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008734 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008735 }
8736 my @AbsPaths = ();
8737 foreach my $File (@Files)
8738 {
8739 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008740 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008741 }
8742 if($Type eq "f" and not -f $File)
8743 { # skip dirs
8744 next;
8745 }
8746 push(@AbsPaths, path_format($File, $OSgroup));
8747 }
8748 if($Type eq "d") {
8749 push(@AbsPaths, $Path);
8750 }
8751 return @AbsPaths;
8752 }
8753 else
8754 {
8755 my $FindCmd = get_CmdPath("find");
8756 if(not $FindCmd) {
8757 exitStatus("Not_Found", "can't find a \"find\" command");
8758 }
8759 $Path = get_abs_path($Path);
8760 if(-d $Path and -l $Path
8761 and $Path!~/\/\Z/)
8762 { # for directories that are symlinks
8763 $Path.="/";
8764 }
8765 my $Cmd = $FindCmd." \"$Path\"";
8766 if($MaxDepth) {
8767 $Cmd .= " -maxdepth $MaxDepth";
8768 }
8769 if($Type) {
8770 $Cmd .= " -type $Type";
8771 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008772 if($Name and not $UseRegex)
8773 { # wildcards
8774 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008775 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008776 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008777 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008778 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8779 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008780 my @Files = split(/\n/, $Res);
8781 if($Name and $UseRegex)
8782 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008783 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008784 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008785 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008786 }
8787}
8788
8789sub unpackDump($)
8790{
8791 my $Path = $_[0];
8792 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008793
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008794 $Path = get_abs_path($Path);
8795 $Path = path_format($Path, $OSgroup);
8796 my ($Dir, $FileName) = separate_path($Path);
8797 my $UnpackDir = $TMP_DIR."/unpack";
8798 rmtree($UnpackDir);
8799 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008800
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008801 if($FileName=~s/\Q.zip\E\Z//g)
8802 { # *.zip
8803 my $UnzipCmd = get_CmdPath("unzip");
8804 if(not $UnzipCmd) {
8805 exitStatus("Not_Found", "can't find \"unzip\" command");
8806 }
8807 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008808 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008810 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 }
8812 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008813 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008814 if(not @Contents) {
8815 exitStatus("Error", "can't extract \'$Path\'");
8816 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008817 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008819 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008820 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008821 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008822 if($OSgroup eq "windows")
8823 { # -xvzf option is not implemented in tar.exe (2003)
8824 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8825 my $TarCmd = get_CmdPath("tar");
8826 if(not $TarCmd) {
8827 exitStatus("Not_Found", "can't find \"tar\" command");
8828 }
8829 my $GzipCmd = get_CmdPath("gzip");
8830 if(not $GzipCmd) {
8831 exitStatus("Not_Found", "can't find \"gzip\" command");
8832 }
8833 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008834 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008835 if($?) {
8836 exitStatus("Error", "can't extract \'$Path\'");
8837 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008838 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008839 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008840 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008841 }
8842 chdir($ORIG_DIR);
8843 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008844 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008845 if(not @Contents) {
8846 exitStatus("Error", "can't extract \'$Path\'");
8847 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008848 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008849 }
8850 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008851 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 my $TarCmd = get_CmdPath("tar");
8853 if(not $TarCmd) {
8854 exitStatus("Not_Found", "can't find \"tar\" command");
8855 }
8856 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008857 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008858 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008859 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860 }
8861 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008862 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008863 if(not @Contents) {
8864 exitStatus("Error", "can't extract \'$Path\'");
8865 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008866 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008867 }
8868 }
8869}
8870
8871sub createArchive($$)
8872{
8873 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008874 if(not $To) {
8875 $To = ".";
8876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008877 if(not $Path or not -e $Path
8878 or not -d $To) {
8879 return "";
8880 }
8881 my ($From, $Name) = separate_path($Path);
8882 if($OSgroup eq "windows")
8883 { # *.zip
8884 my $ZipCmd = get_CmdPath("zip");
8885 if(not $ZipCmd) {
8886 exitStatus("Not_Found", "can't find \"zip\"");
8887 }
8888 my $Pkg = $To."/".$Name.".zip";
8889 unlink($Pkg);
8890 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008891 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 if($?)
8893 { # cannot allocate memory (or other problems with "zip")
8894 unlink($Path);
8895 exitStatus("Error", "can't pack the ABI dump: ".$!);
8896 }
8897 chdir($ORIG_DIR);
8898 unlink($Path);
8899 return $Pkg;
8900 }
8901 else
8902 { # *.tar.gz
8903 my $TarCmd = get_CmdPath("tar");
8904 if(not $TarCmd) {
8905 exitStatus("Not_Found", "can't find \"tar\"");
8906 }
8907 my $GzipCmd = get_CmdPath("gzip");
8908 if(not $GzipCmd) {
8909 exitStatus("Not_Found", "can't find \"gzip\"");
8910 }
8911 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8912 unlink($Pkg);
8913 chdir($From);
8914 system($TarCmd, "-czf", $Pkg, $Name);
8915 if($?)
8916 { # cannot allocate memory (or other problems with "tar")
8917 unlink($Path);
8918 exitStatus("Error", "can't pack the ABI dump: ".$!);
8919 }
8920 chdir($ORIG_DIR);
8921 unlink($Path);
8922 return $To."/".$Name.".tar.gz";
8923 }
8924}
8925
8926sub is_header_file($)
8927{
8928 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8929 return $_[0];
8930 }
8931 return 0;
8932}
8933
8934sub is_not_header($)
8935{
8936 if($_[0]=~/\.\w+\Z/
8937 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8938 return 1;
8939 }
8940 return 0;
8941}
8942
8943sub is_header($$$)
8944{
8945 my ($Header, $UserDefined, $LibVersion) = @_;
8946 return 0 if(-d $Header);
8947 if(-f $Header) {
8948 $Header = get_abs_path($Header);
8949 }
8950 else
8951 {
8952 if(is_abs($Header))
8953 { # incorrect absolute path
8954 return 0;
8955 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008956 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008957 $Header = $HPath;
8958 }
8959 else
8960 { # can't find header
8961 return 0;
8962 }
8963 }
8964 if($Header=~/\.\w+\Z/)
8965 { # have an extension
8966 return is_header_file($Header);
8967 }
8968 else
8969 {
8970 if($UserDefined==2)
8971 { # specified on the command line
8972 if(cmd_file($Header)!~/HTML|XML/i) {
8973 return $Header;
8974 }
8975 }
8976 elsif($UserDefined)
8977 { # specified in the XML-descriptor
8978 # header file without an extension
8979 return $Header;
8980 }
8981 else
8982 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008983 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008984 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008985 { # !~/HTML|XML|shared|dynamic/i
8986 return $Header;
8987 }
8988 }
8989 }
8990 return 0;
8991}
8992
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008993sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008994{
8995 my $LibVersion = $_[0];
8996 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8997 {
8998 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008999 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009000
9001 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9002 detect_recursive_includes($RegHeader, $LibVersion);
9003 }
9004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009005 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9006 {
9007 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009008
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009009 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009010 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9011 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009012 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009013 }
9014 }
9015 }
9016}
9017
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009018sub familiarDirs($$)
9019{
9020 my ($D1, $D2) = @_;
9021 if($D1 eq $D2) {
9022 return 1;
9023 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009024
9025 my $U1 = index($D1, "/usr/");
9026 my $U2 = index($D2, "/usr/");
9027
9028 if($U1==0 and $U2!=0) {
9029 return 0;
9030 }
9031
9032 if($U2==0 and $U1!=0) {
9033 return 0;
9034 }
9035
9036 if(index($D2, $D1."/")==0) {
9037 return 1;
9038 }
9039
9040 # /usr/include/DIR
9041 # /home/user/DIR
9042
9043 my $DL = get_depth($D1);
9044
9045 my @Dirs1 = ($D1);
9046 while($DL - get_depth($D1)<=2
9047 and get_depth($D1)>=4
9048 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9049 push(@Dirs1, $D1);
9050 }
9051
9052 my @Dirs2 = ($D2);
9053 while(get_depth($D2)>=4
9054 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9055 push(@Dirs2, $D2);
9056 }
9057
9058 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009059 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009060 foreach my $P2 (@Dirs2)
9061 {
9062
9063 if($P1 eq $P2) {
9064 return 1;
9065 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009066 }
9067 }
9068 return 0;
9069}
9070
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009071sub readHeaders($)
9072{
9073 $Version = $_[0];
9074 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9075 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009076 if($Debug)
9077 { # debug mode
9078 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009079 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009080 }
9081 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009082}
9083
9084sub prepareTypes($)
9085{
9086 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009087 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009088 { # support for old ABI dumps
9089 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009090 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009091 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009092 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9093 if($TName=~/\A(\w+)::(\w+)/) {
9094 my ($P1, $P2) = ($1, $2);
9095 if($P1 eq $P2) {
9096 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009098 else {
9099 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009101 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009102 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009103 }
9104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009105 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009106 { # support for old ABI dumps
9107 # V < 2.5: array size == "number of elements"
9108 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009109 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009110 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009111 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009112 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009113 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009114 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009115 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009116 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009117 $Size *= $Base{"Size"};
9118 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009119 }
9120 else
9121 { # array[] is a pointer
9122 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009123 }
9124 }
9125 }
9126 }
9127 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009128 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009129 { # support for old ABI dumps
9130 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009131 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009132 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009133 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009134 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009136 my %Type = get_Type($TypeId, $LibVersion);
9137 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9138 my %Type2 = get_Type($TypeId_2, $V2);
9139 if($Type{"Size"} ne $Type2{"Size"}) {
9140 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009141 }
9142 }
9143 }
9144 }
9145}
9146
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009147sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009148{
9149 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009150
9151 if(not keys(%{$SymbolInfo{$LibVersion}}))
9152 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009153 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009154 {
9155 if($CheckHeadersOnly) {
9156 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9157 }
9158 else {
9159 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9160 }
9161 }
9162 }
9163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009164 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009165 if(not checkDump(1, "2.10")
9166 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009167 { # different formats
9168 $Remangle = 1;
9169 }
9170 if($CheckHeadersOnly)
9171 { # different languages
9172 if($UserLang)
9173 { # --lang=LANG for both versions
9174 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9175 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9176 {
9177 if($UserLang eq "C++")
9178 { # remangle symbols
9179 $Remangle = 1;
9180 }
9181 elsif($UserLang eq "C")
9182 { # remove mangling
9183 $Remangle = -1;
9184 }
9185 }
9186 }
9187 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009188
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009189 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009190 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009191 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009192 { # support for old ABI dumps
9193 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9194 {
9195 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9196 {
9197 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9198 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009199 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009200 if(defined $DVal and $DVal ne "")
9201 {
9202 if($TName eq "char") {
9203 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9204 }
9205 elsif($TName eq "bool") {
9206 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9207 }
9208 }
9209 }
9210 }
9211 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009212 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009213 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009214 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9215 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009216 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009217 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9218 # + support for old ABI dumps
9219 next;
9220 }
9221 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009222 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009223 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009224 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009225 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009226
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009227 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009228 if(not checkDump(1, "2.12")
9229 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009230 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009231 if($ShortName eq "operator>>")
9232 {
9233 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9234 { # corrected mangling of operator>>
9235 $SRemangle = 1;
9236 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009237 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009238 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9239 {
9240 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9241 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9242 { # corrected mangling of const global data
9243 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9244 # and incorrectly mangled by old ACC versions
9245 $SRemangle = 1;
9246 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009247 }
9248 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009249 if(not $CheckHeadersOnly)
9250 { # support for old ABI dumps
9251 if(not checkDump(1, "2.17")
9252 or not checkDump(2, "2.17"))
9253 {
9254 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9255 {
9256 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9257 {
9258 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9259 {
9260 $MnglName = $ShortName;
9261 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9262 }
9263 }
9264 }
9265 }
9266 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009267 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009268 { # support for old ABI dumps: some symbols are not mangled in old dumps
9269 # mangle both sets of symbols (old and new)
9270 # NOTE: remangling all symbols by the same mangler
9271 if($MnglName=~/\A_ZN(V|)K/)
9272 { # mangling may be incorrect on old ABI dumps
9273 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009274 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009275 }
9276 if($MnglName=~/\A_ZN(K|)V/)
9277 { # mangling may be incorrect on old ABI dumps
9278 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009279 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009281 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9282 or (not $ClassID and $CheckHeadersOnly)
9283 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9284 { # support for old ABI dumps, GCC >= 4.0
9285 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009286 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009287 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009288 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 $MangledNames{$LibVersion}{$MnglName} = 1;
9290 }
9291 }
9292 }
9293 elsif($Remangle==-1)
9294 { # remove mangling
9295 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009296 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009298 if(not $MnglName) {
9299 next;
9300 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009301
9302 # NOTE: duplicated entries in the ABI Dump
9303 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9304 {
9305 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9306 {
9307 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9308 {
9309 next;
9310 }
9311 }
9312 }
9313
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9315 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009316 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9317
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009319 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009320 { # support for old dumps
9321 # add "Volatile" attribute
9322 if($MnglName=~/_Z(K|)V/) {
9323 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9324 }
9325 }
9326 # symbol and its symlink have same signatures
9327 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009328 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009329 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009330
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009331 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9332 {
9333 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009334
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009335 if($SymVer{$LibVersion}{$Alias}) {
9336 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9337 }
9338 }
9339
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009340 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009341 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009342 }
9343 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9344 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9345 }
9346 if($ExtendedCheck)
9347 { # --ext option
9348 addExtension($LibVersion);
9349 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009350
9351 # clean memory
9352 delete($SymbolInfo{$LibVersion});
9353
9354 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009355 { # detect allocable classes with public exported constructors
9356 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009357 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009358 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009360 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009361 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9362 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009363 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009364 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009365 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009366 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009367 $AllocableClass{$LibVersion}{$ClassName} = 1;
9368 }
9369 }
9370 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009371 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009372 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009373 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009374 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009375 if($CheckHeadersOnly)
9376 {
9377 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9378 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9379 { # all symbols except non-virtual inline
9380 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9381 }
9382 }
9383 else {
9384 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 }
9386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009387 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009388 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009389 }
9390 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009391 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009392 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009393 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009394 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009395 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009396 if(defined $Base{"Type"}
9397 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009399 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009400 if($Name=~/<([^<>\s]+)>/)
9401 {
9402 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9403 $ReturnedClass{$LibVersion}{$Tid} = 1;
9404 }
9405 }
9406 else {
9407 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9408 }
9409 }
9410 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009411 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009413 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009414 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009415 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009416 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009417 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009418 if($Base{"Type"}=~/Struct|Class/)
9419 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009420 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009421 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9422 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009423 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009425 }
9426 }
9427 }
9428 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009429
9430 # mapping {short name => symbols}
9431 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009432 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009433 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009434 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009435 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009436 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009437 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009438 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009439 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9440 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009441 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009442 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 }
9444 }
9445 }
9446 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009447
9448 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009449 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009451 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009452 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009453 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9454 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009455 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009456 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009458 $ClassNames{$LibVersion}{$TName} = 1;
9459 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009460 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009461 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9462 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009463 }
9464 }
9465 }
9466 }
9467 }
9468}
9469
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009470sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009471{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009472 my ($Tid, $LibVersion) = @_;
9473 if(not $Tid) {
9474 return $Tid;
9475 }
9476
9477 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9478 {
9479 if($TName_Tid{$LibVersion}{$Name}) {
9480 return $TName_Tid{$LibVersion}{$Name};
9481 }
9482 }
9483
9484 return $Tid;
9485}
9486
9487sub register_SymbolUsage($$$)
9488{
9489 my ($InfoId, $UsedType, $LibVersion) = @_;
9490
9491 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9492 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9493 {
9494 register_TypeUsage($RTid, $UsedType, $LibVersion);
9495 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9496 }
9497 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9498 {
9499 register_TypeUsage($FCid, $UsedType, $LibVersion);
9500 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9501
9502 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9503 { # register "this" pointer
9504 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9505 }
9506 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9507 { # register "this" pointer (const method)
9508 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9509 }
9510 }
9511 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9512 {
9513 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9514 {
9515 register_TypeUsage($PTid, $UsedType, $LibVersion);
9516 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9517 }
9518 }
9519 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9520 {
9521 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9522 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9523 register_TypeUsage($TTid, $UsedType, $LibVersion);
9524 }
9525 }
9526}
9527
9528sub register_TypeUsage($$$)
9529{
9530 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009531 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009532 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009533 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009534 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009535 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009536 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009537 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009538
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009539 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009540 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009541 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009542 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009543 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009544 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9545 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9546 }
9547 }
9548
9549 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9550 {
9551 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009552 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009553 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009554 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9555 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009556 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009557 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9558 {
9559 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9560 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009561 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009562 }
9563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009564 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009565 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009566 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009567 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9568 {
9569 register_TypeUsage($MTid, $UsedType, $LibVersion);
9570 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009571 }
9572 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009573 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009574 or $TInfo{"Type"} eq "MethodPtr"
9575 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009576 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009577 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009578 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009579 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009580 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009581 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009582 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9583 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009584 }
9585 }
9586 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009587 if($TInfo{"Type"} eq "FieldPtr")
9588 {
9589 if(my $RTid = $TInfo{"Return"}) {
9590 register_TypeUsage($RTid, $UsedType, $LibVersion);
9591 }
9592 if(my $CTid = $TInfo{"Class"}) {
9593 register_TypeUsage($CTid, $UsedType, $LibVersion);
9594 }
9595 }
9596 if($TInfo{"Type"} eq "MethodPtr")
9597 {
9598 if(my $CTid = $TInfo{"Class"}) {
9599 register_TypeUsage($CTid, $UsedType, $LibVersion);
9600 }
9601 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009602 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009603 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009604 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009605 $UsedType->{$TypeId} = 1;
9606 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9607 {
9608 register_TypeUsage($BTid, $UsedType, $LibVersion);
9609 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9610 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009611 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009612 else
9613 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9614 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009615 }
9616 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009617}
9618
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009619sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009620{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009621 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9622
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009623 if($Level eq "Dump")
9624 {
9625 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9626 { # TODO: check if this symbol is from
9627 # base classes of other target symbols
9628 return 1;
9629 }
9630 }
9631
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009632 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9633 { # stdc++ interfaces
9634 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009635 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009636
9637 my $Target = 0;
9638 if(my $Header = $SInfo->{"Header"}) {
9639 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9640 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009641 if($ExtendedCheck)
9642 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009643 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009644 $Target = 1;
9645 }
9646 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009647 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009648 {
9649 if($Target)
9650 {
9651 if($Level eq "Dump")
9652 { # dumped
9653 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009654 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009655 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009656 return 1;
9657 }
9658 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009659 else {
9660 return 1;
9661 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009662 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009663 elsif($Level eq "Source")
9664 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009665 return 1;
9666 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009667 elsif($Level eq "Binary")
9668 { # checked
9669 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9670 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9671 return 1;
9672 }
9673 }
9674 }
9675 }
9676 else
9677 { # library is available
9678 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9679 { # exported symbols
9680 return 1;
9681 }
9682 if($Level eq "Dump")
9683 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009684 if($BinaryOnly)
9685 {
9686 if($SInfo->{"Data"})
9687 {
9688 if($Target) {
9689 return 1;
9690 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009691 }
9692 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009693 else
9694 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009695 if($Target) {
9696 return 1;
9697 }
9698 }
9699 }
9700 elsif($Level eq "Source")
9701 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009702 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009703 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009704 { # skip LOCAL symbols
9705 if($Target) {
9706 return 1;
9707 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009708 }
9709 }
9710 elsif($Level eq "Binary")
9711 { # checked
9712 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9713 {
9714 if($Target) {
9715 return 1;
9716 }
9717 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009718 }
9719 }
9720 return 0;
9721}
9722
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009723sub cleanDump($)
9724{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009725 my $LibVersion = $_[0];
9726 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9727 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009728 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9729 {
9730 delete($SymbolInfo{$LibVersion}{$InfoId});
9731 next;
9732 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009733 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009734 if(not $MnglName)
9735 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009736 delete($SymbolInfo{$LibVersion}{$InfoId});
9737 next;
9738 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009739 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009740 if(not $ShortName)
9741 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009742 delete($SymbolInfo{$LibVersion}{$InfoId});
9743 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009745 if($MnglName eq $ShortName)
9746 { # remove duplicate data
9747 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009748 }
9749 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9750 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9751 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009752 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9753 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9754 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009755 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009756 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009757 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009758 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009759 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9760 {
9761 delete($TypeInfo{$LibVersion}{$Tid});
9762 next;
9763 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009764 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009765 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009766 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009767 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9768 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9769 }
9770 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009771 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9772 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9773 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009774 }
9775}
9776
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009777sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009778{
9779 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009780
9781 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9782 {
9783 if(defined $TypeInfo{$LibVersion}{$Dupl})
9784 {
9785 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9786 { # duplicate
9787 return 0;
9788 }
9789 }
9790 }
9791
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009792 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9793
9794 if(isBuiltIn($THeader)) {
9795 return 0;
9796 }
9797
9798 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9799 return 0;
9800 }
9801
9802 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9803 return 0;
9804 }
9805
9806 if(selfTypedef($Tid, $LibVersion)) {
9807 return 0;
9808 }
9809
9810 if(not isTargetType($Tid, $LibVersion)) {
9811 return 0;
9812 }
9813
9814 return 0;
9815}
9816
9817sub isTargetType($$)
9818{
9819 my ($Tid, $LibVersion) = @_;
9820
9821 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9822 { # derived
9823 return 1;
9824 }
9825
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009826 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009827 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009828 if(not is_target_header($THeader, $LibVersion))
9829 { # from target headers
9830 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009831 }
9832 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009833 else
9834 { # NOTE: if type is defined in source
9835 if($UsedDump{$LibVersion}{"Public"})
9836 {
9837 if(isPrivateABI($Tid, $LibVersion)) {
9838 return 0;
9839 }
9840 else {
9841 return 1;
9842 }
9843 }
9844 else {
9845 return 0;
9846 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009847 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009848
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009849 if($SkipInternalTypes)
9850 {
9851 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9852 {
9853 return 0;
9854 }
9855 }
9856
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009857 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009858}
9859
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009860sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009861{ # remove unused data types from the ABI dump
9862 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009863
9864 my %UsedType = ();
9865
9866 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009867 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009868 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009869 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009870 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009871 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009872 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009873 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009874 next;
9875 }
9876
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009877 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009878 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009879 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009880 {
9881 my %Tree = ();
9882 register_TypeUsage($Tid, \%Tree, $LibVersion);
9883
9884 my $Tmpl = 0;
9885 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9886 {
9887 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9888 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9889 {
9890 $Tmpl = 1;
9891 last;
9892 }
9893 }
9894 if(not $Tmpl)
9895 {
9896 foreach (keys(%Tree)) {
9897 $UsedType{$_} = 1;
9898 }
9899 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009900 }
9901 }
9902 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009903
9904 my %Delete = ();
9905
9906 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009907 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009908 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009909 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009910 next;
9911 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009912
9913 if($Kind eq "Extra")
9914 {
9915 my %Tree = ();
9916 register_TypeUsage($Tid, \%Tree, $LibVersion);
9917
9918 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9919 {
9920 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9921 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9922 {
9923 $Delete{$Tid} = 1;
9924 last;
9925 }
9926 }
9927 }
9928 else
9929 {
9930 # remove type
9931 delete($TypeInfo{$LibVersion}{$Tid});
9932 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009933 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009934
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009935 if($Kind eq "Extra")
9936 { # remove duplicates
9937 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9938 {
9939 if($UsedType{$Tid})
9940 { # All & Extended
9941 next;
9942 }
9943
9944 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9945
9946 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9947 delete($TypeInfo{$LibVersion}{$Tid});
9948 }
9949 }
9950 }
9951
9952 foreach my $Tid (keys(%Delete))
9953 {
9954 delete($TypeInfo{$LibVersion}{$Tid});
9955 }
9956}
9957
9958sub check_Completeness($$)
9959{
9960 my ($Info, $LibVersion) = @_;
9961
9962 # data types
9963 if(defined $Info->{"Memb"})
9964 {
9965 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9966 {
9967 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9968 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9969 }
9970 }
9971 }
9972 if(defined $Info->{"Base"})
9973 {
9974 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9975 check_TypeInfo($Bid, $LibVersion);
9976 }
9977 }
9978 if(defined $Info->{"BaseType"}) {
9979 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9980 }
9981 if(defined $Info->{"TParam"})
9982 {
9983 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9984 {
9985 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9986 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9987 next;
9988 }
9989 if($TName eq "_BoolType") {
9990 next;
9991 }
9992 if($TName=~/\Asizeof\(/) {
9993 next;
9994 }
9995 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9996 check_TypeInfo($Tid, $LibVersion);
9997 }
9998 else
9999 {
10000 if(defined $Debug) {
10001 printMsg("WARNING", "missed type $TName");
10002 }
10003 }
10004 }
10005 }
10006
10007 # symbols
10008 if(defined $Info->{"Param"})
10009 {
10010 foreach my $Pos (keys(%{$Info->{"Param"}}))
10011 {
10012 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10013 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10014 }
10015 }
10016 }
10017 if(defined $Info->{"Return"}) {
10018 check_TypeInfo($Info->{"Return"}, $LibVersion);
10019 }
10020 if(defined $Info->{"Class"}) {
10021 check_TypeInfo($Info->{"Class"}, $LibVersion);
10022 }
10023}
10024
10025sub check_TypeInfo($$)
10026{
10027 my ($Tid, $LibVersion) = @_;
10028
10029 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10030 return;
10031 }
10032 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10033
10034 if(defined $TypeInfo{$LibVersion}{$Tid})
10035 {
10036 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10037 printMsg("ERROR", "missed type name ($Tid)");
10038 }
10039 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10040 }
10041 else {
10042 printMsg("ERROR", "missed type id $Tid");
10043 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010044}
10045
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010046sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010047{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010048 my ($TypeId, $LibVersion) = @_;
10049 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010050 if($Type{"Type"} eq "Typedef")
10051 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010052 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010053 if($Base{"Type"}=~/Class|Struct/)
10054 {
10055 if($Type{"Name"} eq $Base{"Name"}) {
10056 return 1;
10057 }
10058 elsif($Type{"Name"}=~/::(\w+)\Z/)
10059 {
10060 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10061 { # QPointer<QWidget>::QPointer
10062 return 1;
10063 }
10064 }
10065 }
10066 }
10067 return 0;
10068}
10069
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010070sub addExtension($)
10071{
10072 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010073 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010074 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010075 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010076 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010077 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10078 $TName=~s/\A(struct|union|class|enum) //;
10079 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010080
10081 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10082 "Header" => "extended.h",
10083 "ShortName" => $Symbol,
10084 "MnglName" => $Symbol,
10085 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10086 );
10087
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010088 $ExtendedSymbols{$Symbol} = 1;
10089 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10090 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010091 }
10092 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010093 $ExtendedSymbols{"external_func_0"} = 1;
10094 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10095 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010096}
10097
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010098sub findMethod($$$)
10099{
10100 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010101 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010102 {
10103 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10104 return $VirtMethodInClass;
10105 }
10106 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10107 return $VirtMethodInBaseClasses;
10108 }
10109 }
10110 return "";
10111}
10112
10113sub findMethod_Class($$$)
10114{
10115 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010116 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010117 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10118 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10119 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10120 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10121 { # search for interface with the same parameters suffix (overridden)
10122 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10123 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010124 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10125 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010126 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10127 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010128 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10129 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10130 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10131 return $Candidate;
10132 }
10133 }
10134 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010135 else
10136 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010137 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10138 return $Candidate;
10139 }
10140 }
10141 }
10142 }
10143 return "";
10144}
10145
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010146sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010147{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010148 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010149 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010150 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010151 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10152 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010153 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010154 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010156 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10157 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010158 { # pure virtual D2-destructors are marked as "virt" in the dump
10159 # virtual D2-destructors are NOT marked as "virt" in the dump
10160 # both destructors are not presented in the v-table
10161 next;
10162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010163 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010164 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010166 }
10167}
10168
10169sub registerOverriding($)
10170{
10171 my $LibVersion = $_[0];
10172 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010173 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010174 foreach my $ClassName (@Classes)
10175 {
10176 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10177 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010178 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10179 { # pure virtuals
10180 next;
10181 }
10182 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10183 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010184 {
10185 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10186 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10187 { # both overridden virtual methods
10188 # and implemented pure virtual methods
10189 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10190 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10191 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010193 }
10194 }
10195 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10196 delete($VirtualTable{$LibVersion}{$ClassName});
10197 }
10198 }
10199}
10200
10201sub setVirtFuncPositions($)
10202{
10203 my $LibVersion = $_[0];
10204 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10205 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010206 my ($Num, $Rel) = (1, 0);
10207
10208 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010209 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010210 if($UsedDump{$LibVersion}{"DWARF"}) {
10211 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10212 }
10213 else {
10214 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10215 }
10216 foreach my $VirtFunc (@Funcs)
10217 {
10218 if($UsedDump{$LibVersion}{"DWARF"}) {
10219 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10220 }
10221 else {
10222 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10223 }
10224
10225 # set relative positions
10226 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10227 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10228 { # relative position excluding added and removed virtual functions
10229 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10230 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10231 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010235 }
10236 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010237 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010238 {
10239 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010240 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010241 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010242 }
10243 }
10244}
10245
10246sub get_sub_classes($$$)
10247{
10248 my ($ClassId, $LibVersion, $Recursive) = @_;
10249 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10250 my @Subs = ();
10251 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10252 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010253 if($Recursive)
10254 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010255 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10256 push(@Subs, $SubSubId);
10257 }
10258 }
10259 push(@Subs, $SubId);
10260 }
10261 return @Subs;
10262}
10263
10264sub get_base_classes($$$)
10265{
10266 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010267 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010268 return () if(not defined $ClassType{"Base"});
10269 my @Bases = ();
10270 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10271 keys(%{$ClassType{"Base"}}))
10272 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010273 if($Recursive)
10274 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010275 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10276 push(@Bases, $SubBaseId);
10277 }
10278 }
10279 push(@Bases, $BaseId);
10280 }
10281 return @Bases;
10282}
10283
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010284sub getVTable_Model($$)
10285{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010286 my ($ClassId, $LibVersion) = @_;
10287 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10288 my @Elements = ();
10289 foreach my $BaseId (@Bases, $ClassId)
10290 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010291 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010292 {
10293 if(defined $VirtualTable{$LibVersion}{$BName})
10294 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010295 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10296 if($UsedDump{$LibVersion}{"DWARF"}) {
10297 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10298 }
10299 else {
10300 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10301 }
10302 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010303 push(@Elements, $VFunc);
10304 }
10305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010306 }
10307 }
10308 return @Elements;
10309}
10310
10311sub getVShift($$)
10312{
10313 my ($ClassId, $LibVersion) = @_;
10314 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10315 my $VShift = 0;
10316 foreach my $BaseId (@Bases)
10317 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010318 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010319 {
10320 if(defined $VirtualTable{$LibVersion}{$BName}) {
10321 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010323 }
10324 }
10325 return $VShift;
10326}
10327
10328sub getShift($$)
10329{
10330 my ($ClassId, $LibVersion) = @_;
10331 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10332 my $Shift = 0;
10333 foreach my $BaseId (@Bases)
10334 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010335 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010336 {
10337 if($Size!=1)
10338 { # not empty base class
10339 $Shift+=$Size;
10340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010341 }
10342 }
10343 return $Shift;
10344}
10345
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010346sub getVTable_Size($$)
10347{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010348 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010349 my $Size = 0;
10350 # three approaches
10351 if(not $Size)
10352 { # real size
10353 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10354 $Size = keys(%VTable);
10355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010356 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010357 if(not $Size)
10358 { # shared library symbol size
10359 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10360 $Size /= $WORD_SIZE{$LibVersion};
10361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010362 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010363 if(not $Size)
10364 { # model size
10365 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10366 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10367 }
10368 }
10369 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010370}
10371
10372sub isCopyingClass($$)
10373{
10374 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010375 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010376}
10377
10378sub isLeafClass($$)
10379{
10380 my ($ClassId, $LibVersion) = @_;
10381 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10382}
10383
10384sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010385{ # check structured type for public fields
10386 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010387}
10388
10389sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010390{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010391 my ($TypePtr, $Skip, $Start, $End) = @_;
10392 return 0 if(not $TypePtr);
10393 if($End==-1) {
10394 $End = keys(%{$TypePtr->{"Memb"}})-1;
10395 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010396 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010397 {
10398 if($Skip and $Skip->{$MemPos})
10399 { # skip removed/added fields
10400 next;
10401 }
10402 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10403 {
10404 if(isPublic($TypePtr, $MemPos)) {
10405 return ($MemPos+1);
10406 }
10407 }
10408 }
10409 return 0;
10410}
10411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010412sub isReserved($)
10413{ # reserved fields == private
10414 my $MName = $_[0];
10415 if($MName=~/reserved|padding|f_spare/i) {
10416 return 1;
10417 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010418 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010419 return 1;
10420 }
10421 if($MName=~/(pad\d+)/i) {
10422 return 1;
10423 }
10424 return 0;
10425}
10426
10427sub isPublic($$)
10428{
10429 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010430
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010431 return 0 if(not $TypePtr);
10432 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10433 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010434
10435 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10436 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010437 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010438 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010439 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010440
10441 # by name in C language
10442 # TODO: add other methods to detect private members
10443 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10444 if($MName=~/priv|abidata|parent_object/i)
10445 { # C-styled private data
10446 return 0;
10447 }
10448 if(lc($MName) eq "abi")
10449 { # ABI information/reserved field
10450 return 0;
10451 }
10452 if(isReserved($MName))
10453 { # reserved fields
10454 return 0;
10455 }
10456
10457 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458}
10459
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010460sub getVTable_Real($$)
10461{
10462 my ($ClassName, $LibVersion) = @_;
10463 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10464 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010465 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010466 if(defined $Type{"VTable"}) {
10467 return %{$Type{"VTable"}};
10468 }
10469 }
10470 return ();
10471}
10472
10473sub cmpVTables($)
10474{
10475 my $ClassName = $_[0];
10476 my $Res = cmpVTables_Real($ClassName, 1);
10477 if($Res==-1) {
10478 $Res = cmpVTables_Model($ClassName);
10479 }
10480 return $Res;
10481}
10482
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010483sub cmpVTables_Model($)
10484{
10485 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010486 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010488 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489 return 1;
10490 }
10491 }
10492 return 0;
10493}
10494
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010495sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496{
10497 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010498 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10499 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010500 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010501 my %VTable_Old = getVTable_Real($ClassName, 1);
10502 my %VTable_New = getVTable_Real($ClassName, 2);
10503 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010504 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010505 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010506 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010507 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010508 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10509 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010510 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010511 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010512 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010514 my $Entry1 = $VTable_Old{$Offset};
10515 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010516 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010517 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010519 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521 $Entry1 = simpleVEntry($Entry1);
10522 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010523
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010524 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010525 { # NOTE: problem with vtable-dumper
10526 next;
10527 }
10528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 if($Entry1 ne $Entry2)
10530 { # register as changed
10531 if($Entry1=~/::([^:]+)\Z/)
10532 {
10533 my $M1 = $1;
10534 if($Entry2=~/::([^:]+)\Z/)
10535 {
10536 my $M2 = $1;
10537 if($M1 eq $M2)
10538 { # overridden
10539 next;
10540 }
10541 }
10542 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010543 if(differentDumps("G"))
10544 {
10545 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10546 {
10547 # GCC 4.6.1: -0x00000000000000010
10548 # GCC 4.7.0: -16
10549 next;
10550 }
10551 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553 }
10554 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010556}
10557
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010558sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010559{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010560 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10562 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010563 my $ClassId = $TName_Tid{1}{$ClassName};
10564 if(isPrivateABI($ClassId, 1)) {
10565 next;
10566 }
10567
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010568 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010569 { # already registered
10570 next;
10571 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010572 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010574 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010575 foreach my $Symbol (@Affected)
10576 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010577 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 "Target"=>$ClassName);
10580 }
10581 }
10582 }
10583}
10584
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010585sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010587 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010588 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010589 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010590 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010591 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010592
10593 if(isPrivateABI($ClassId, 1)) {
10594 next;
10595 }
10596
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010597 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010598 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010599 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010600 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010601 if($TName_Tid{1}{$ClassName}
10602 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010603 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010604 if(defined $CompleteSignature{1}{$Symbol}
10605 and $CompleteSignature{1}{$Symbol}{"Virt"})
10606 { # override some method in v.1
10607 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010608 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010609 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010610 }
10611 }
10612 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010613 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010614 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010615 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010616 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010617 if($TName_Tid{2}{$ClassName}
10618 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010619 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010620 if(defined $CompleteSignature{2}{$Symbol}
10621 and $CompleteSignature{2}{$Symbol}{"Virt"})
10622 { # override some method in v.2
10623 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010624 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010625 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010626 }
10627 }
10628 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010629 if($Level eq "Binary")
10630 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010631 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010632 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10633 { # check replacements, including pure virtual methods
10634 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10635 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010636 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010637 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10638 if($AddedPos==$RemovedPos)
10639 {
10640 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10641 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10642 last; # other methods will be reported as "added" or "removed"
10643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010644 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010645 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10646 {
10647 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10648 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010649 next;
10650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010651 my $ProblemType = "Virtual_Replacement";
10652 my @Affected = ($RemovedVFunc);
10653 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10654 { # pure methods
10655 if(not isUsedClass($ClassId, 1, $Level))
10656 { # not a parameter of some exported method
10657 next;
10658 }
10659 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010660
10661 # affected all methods (both virtual and non-virtual ones)
10662 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10663 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010664 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010665 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010666 foreach my $AffectedInt (@Affected)
10667 {
10668 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10669 { # affected exported methods only
10670 next;
10671 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010672 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10673 next;
10674 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010675 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10676 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010677 "Target"=>get_Signature($AddedVFunc, 2),
10678 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010680 }
10681 }
10682 }
10683 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010684 if(not checkDump(1, "2.0")
10685 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010686 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010687 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 return;
10689 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010690 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010691 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010692 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010693 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010694
10695 if(isPrivateABI($ClassId_Old, 1)) {
10696 next;
10697 }
10698
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010699 if(not isCreatable($ClassId_Old, 1))
10700 { # skip classes without public constructors (including auto-generated)
10701 # example: class has only a private exported or private inline constructor
10702 next;
10703 }
10704 if($ClassName=~/>/)
10705 { # skip affected template instances
10706 next;
10707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010708 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010709 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010710 if(not $ClassId_New) {
10711 next;
10712 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010713 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010714 if($Class_New{"Type"}!~/Class|Struct/)
10715 { # became typedef
10716 if($Level eq "Binary") {
10717 next;
10718 }
10719 if($Level eq "Source")
10720 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010721 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010722 if($Class_New{"Type"}!~/Class|Struct/) {
10723 next;
10724 }
10725 $ClassId_New = $Class_New{"Tid"};
10726 }
10727 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010728
10729 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10730 { # incomplete info in the ABI dump
10731 next;
10732 }
10733
10734
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010735 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10736 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 +040010737
10738 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10739 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10740
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010741 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010742 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10743 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010744 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10745 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010746 my $Shift_Old = getShift($ClassId_Old, 1);
10747 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010748 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010749 my ($Added, $Removed) = (0, 0);
10750 my @StableBases_Old = ();
10751 foreach my $BaseId (@Bases_Old)
10752 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010753 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010754 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010755 push(@StableBases_Old, $BaseId);
10756 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010757 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010758 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 { # removed base
10760 # excluding namespace::SomeClass to SomeClass renaming
10761 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010762 if($Level eq "Binary")
10763 { # Binary-level
10764 if($Shift_Old ne $Shift_New)
10765 { # affected fields
10766 if(havePubFields(\%Class_Old)) {
10767 $ProblemKind .= "_And_Shift";
10768 }
10769 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10770 $ProblemKind .= "_And_Size";
10771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010772 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010773 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10774 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010775 { # affected v-table
10776 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010777 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 }
10779 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010780 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010781 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10782 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010783 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10784 {
10785 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10786 if($ProblemKind=~/VTable/) {
10787 $VTableChanged_M{$SubName}=1;
10788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010789 }
10790 }
10791 foreach my $Interface (@Affected)
10792 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010793 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10794 next;
10795 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010796 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010797 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 "Target"=>$BaseName,
10799 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10800 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10801 "Shift"=>abs($Shift_New-$Shift_Old) );
10802 }
10803 $Removed+=1;
10804 }
10805 }
10806 my @StableBases_New = ();
10807 foreach my $BaseId (@Bases_New)
10808 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010809 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010810 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010811 push(@StableBases_New, $BaseId);
10812 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010813 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010814 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010815 { # added base
10816 # excluding namespace::SomeClass to SomeClass renaming
10817 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010818 if($Level eq "Binary")
10819 { # Binary-level
10820 if($Shift_Old ne $Shift_New)
10821 { # affected fields
10822 if(havePubFields(\%Class_Old)) {
10823 $ProblemKind .= "_And_Shift";
10824 }
10825 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10826 $ProblemKind .= "_And_Size";
10827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010828 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010829 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10830 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010831 { # affected v-table
10832 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010833 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010834 }
10835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010836 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10838 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010839 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10840 {
10841 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10842 if($ProblemKind=~/VTable/) {
10843 $VTableChanged_M{$SubName}=1;
10844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010845 }
10846 }
10847 foreach my $Interface (@Affected)
10848 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010849 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10850 next;
10851 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010852 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010853 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010854 "Target"=>$BaseName,
10855 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10856 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10857 "Shift"=>abs($Shift_New-$Shift_Old) );
10858 }
10859 $Added+=1;
10860 }
10861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010862 if($Level eq "Binary")
10863 { # Binary-level
10864 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010865 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10866 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010867 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010869 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010870 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010871 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010872 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10873 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 if($NewPos!=$OldPos)
10875 { # changed position of the base class
10876 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010877 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010878 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10879 next;
10880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10882 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010883 "Target"=>$BaseName,
10884 "Old_Value"=>$OldPos-1,
10885 "New_Value"=>$NewPos-1 );
10886 }
10887 }
10888 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10889 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10890 { # became non-virtual base
10891 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10892 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010893 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10894 next;
10895 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10897 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010898 "Target"=>$BaseName );
10899 }
10900 }
10901 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10902 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10903 { # became virtual base
10904 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10905 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010906 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10907 next;
10908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10910 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010911 "Target"=>$BaseName );
10912 }
10913 }
10914 }
10915 }
10916 # detect size changes in base classes
10917 if($Shift_Old!=$Shift_New)
10918 { # size of allocable class
10919 foreach my $BaseId (@StableBases_Old)
10920 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010921 my %BaseType = get_Type($BaseId, 1);
10922 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010923 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 if($Size_Old ne $Size_New
10925 and $Size_Old and $Size_New)
10926 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010927 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 if(isCopyingClass($BaseId, 1)) {
10929 $ProblemType = "Size_Of_Copying_Class";
10930 }
10931 elsif($AllocableClass{1}{$BaseType{"Name"}})
10932 {
10933 if($Size_New>$Size_Old)
10934 { # increased size
10935 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 else
10938 { # decreased size
10939 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10940 if(not havePubFields(\%Class_Old))
10941 { # affected class has no public members
10942 next;
10943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010944 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010945 }
10946 next if(not $ProblemType);
10947 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10948 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010949 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10950 next;
10951 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10953 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010954 "Target"=>$BaseType{"Name"},
10955 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10956 "New_Size"=>$Size_New*$BYTE_SIZE );
10957 }
10958 }
10959 }
10960 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010961 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010962 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010963 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010964 { # compare virtual tables size in base classes
10965 my $VShift_Old = getVShift($ClassId_Old, 1);
10966 my $VShift_New = getVShift($ClassId_New, 2);
10967 if($VShift_Old ne $VShift_New)
10968 { # changes in the base class or changes in the list of base classes
10969 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10970 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10971 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010972 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010973 foreach my $BaseId (@AllBases_Old)
10974 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010975 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010976 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010977 { # lost base
10978 next;
10979 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010980 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10981 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010982 if($VSize_Old!=$VSize_New)
10983 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010984 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010985 { # TODO: affected non-virtual methods?
10986 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10988 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010989 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010990 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010991 { # skip interfaces that have not changed the absolute virtual position
10992 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010993 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010994 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10995 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010996 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010997 $VTableChanged_M{$BaseType{"Name"}} = 1;
10998 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010999 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11000 { # the reason of the layout change: added virtual functions
11001 next if($VirtualReplacement{$VirtFunc});
11002 my $ProblemType = "Added_Virtual_Method";
11003 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11004 $ProblemType = "Added_Pure_Virtual_Method";
11005 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011006 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011007 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011008 "Target"=>get_Signature($VirtFunc, 2) );
11009 }
11010 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11011 { # the reason of the layout change: removed virtual functions
11012 next if($VirtualReplacement{$VirtFunc});
11013 my $ProblemType = "Removed_Virtual_Method";
11014 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11015 $ProblemType = "Removed_Pure_Virtual_Method";
11016 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011017 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011018 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011019 "Target"=>get_Signature($VirtFunc, 1) );
11020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011021 }
11022 }
11023 }
11024 }
11025 }
11026 }
11027 }
11028}
11029
11030sub isCreatable($$)
11031{
11032 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011033 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011034 or isCopyingClass($ClassId, $LibVersion)) {
11035 return 1;
11036 }
11037 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11038 { # Fix for incomplete data: if this class has
11039 # a base class then it should also has a constructor
11040 return 1;
11041 }
11042 if($ReturnedClass{$LibVersion}{$ClassId})
11043 { # returned by some method of this class
11044 # or any other class
11045 return 1;
11046 }
11047 return 0;
11048}
11049
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011050sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011051{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011053 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11054 { # parameter of some exported method
11055 return 1;
11056 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011057 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11058 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 { # method from target class
11060 return 1;
11061 }
11062 return 0;
11063}
11064
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011066{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011067 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011068 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011069 # - virtual
11070 # - pure-virtual
11071 # - non-virtual
11072 if($CompleteSignature{1}{$Interface}{"Data"})
11073 { # global data is not affected
11074 return;
11075 }
11076 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011077 if(not $Class_Id) {
11078 return;
11079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011080 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011081 if(cmpVTables_Real($CName, 1)==0)
11082 { # no changes
11083 return;
11084 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011085 $CheckedTypes{$Level}{$CName} = 1;
11086 if($Level eq "Binary")
11087 { # Binary-level
11088 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11089 and not isUsedClass($Class_Id, 1, $Level))
11090 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011091 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011092 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011093 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011094 }
11095 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11096 {
11097 if(defined $VirtualTable{2}{$CName}{$Func}
11098 and defined $CompleteSignature{2}{$Func})
11099 {
11100 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11101 and $CompleteSignature{2}{$Func}{"PureVirt"})
11102 { # became pure virtual
11103 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11104 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011105 "Target"=>get_Signature_M($Func, 1) );
11106 $VTableChanged_M{$CName} = 1;
11107 }
11108 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11109 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11110 { # became non-pure virtual
11111 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11112 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011113 "Target"=>get_Signature_M($Func, 1) );
11114 $VTableChanged_M{$CName} = 1;
11115 }
11116 }
11117 }
11118 if($Level eq "Binary")
11119 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011120 # check virtual table structure
11121 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11122 {
11123 next if($Interface eq $AddedVFunc);
11124 next if($VirtualReplacement{$AddedVFunc});
11125 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11126 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11127 { # pure virtual methods affect all others (virtual and non-virtual)
11128 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011130 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011131 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011132 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011133 elsif(not defined $VirtualTable{1}{$CName}
11134 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011136 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 { # became polymorphous class, added v-table pointer
11138 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011139 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011140 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011141 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011142 }
11143 else
11144 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011145 my $VSize_Old = getVTable_Size($CName, 1);
11146 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011147 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 if(isCopyingClass($Class_Id, 1))
11149 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11150 my $ProblemType = "Added_Virtual_Method";
11151 if(isLeafClass($Class_Id, 1)) {
11152 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11153 }
11154 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11155 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011156 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011157 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011158 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011159 else
11160 {
11161 my $ProblemType = "Added_Virtual_Method";
11162 if(isLeafClass($Class_Id, 1)) {
11163 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11164 }
11165 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11166 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011167 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011168 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011170 }
11171 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011172 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11173 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011174 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011175 if(defined $VirtualTable{1}{$CName}
11176 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011177 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011178 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11179 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011180
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011181 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011182 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011183 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11184 foreach my $ASymbol (@Affected)
11185 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011186 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11187 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011188 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011189 next;
11190 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011191 }
11192 $CheckedSymbols{$Level}{$ASymbol} = 1;
11193 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11194 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011195 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011196 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011199 }
11200 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 else {
11202 # safe
11203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11206 {
11207 next if($VirtualReplacement{$RemovedVFunc});
11208 if($RemovedVFunc eq $Interface
11209 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11210 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011211 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011212 next;
11213 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011214 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011215 { # became non-polymorphous class, removed v-table pointer
11216 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11217 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011218 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011220 }
11221 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11222 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11223 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011224 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011225 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011226 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11227 next;
11228 }
11229 my $VPos_New = -1;
11230 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011231 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011232 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11233 }
11234 else
11235 {
11236 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 next;
11238 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011239 }
11240 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11241 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11242 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11243 {
11244 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11245 foreach my $ASymbol (@Affected)
11246 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011247 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11248 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011249 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011250 next;
11251 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011252 }
11253 my $ProblemType = "Removed_Virtual_Method";
11254 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11255 $ProblemType = "Removed_Pure_Virtual_Method";
11256 }
11257 $CheckedSymbols{$Level}{$ASymbol} = 1;
11258 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11259 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011260 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011261 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011263 }
11264 }
11265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011266 }
11267 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011268 else
11269 { # Source-level
11270 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011271 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011272 next if($Interface eq $AddedVFunc);
11273 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011274 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11276 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011277 "Target"=>get_Signature($AddedVFunc, 2) );
11278 }
11279 }
11280 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11281 {
11282 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11283 {
11284 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11285 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011286 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011287 }
11288 }
11289 }
11290}
11291
11292sub find_MemberPair_Pos_byName($$)
11293{
11294 my ($Member_Name, $Pair_Type) = @_;
11295 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11296 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11297 {
11298 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11299 {
11300 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11301 $Name=~s/\A[_]+|[_]+\Z//g;
11302 if($Name eq $Member_Name) {
11303 return $MemberPair_Pos;
11304 }
11305 }
11306 }
11307 return "lost";
11308}
11309
11310sub find_MemberPair_Pos_byVal($$)
11311{
11312 my ($Member_Value, $Pair_Type) = @_;
11313 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11314 {
11315 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11316 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11317 return $MemberPair_Pos;
11318 }
11319 }
11320 return "lost";
11321}
11322
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011323sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011324{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011325 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011326 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011327 if( $_->{"T1"} eq $_[0]
11328 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011329 {
11330 return 1;
11331 }
11332 }
11333 return 0;
11334}
11335
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011336sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011337{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011338 my %IDs = (
11339 "T1" => $_[0],
11340 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011341 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011342 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011343}
11344
11345sub isRenamed($$$$$)
11346{
11347 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11348 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11349 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011350 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011351 if(not defined $Type2->{"Memb"}{$MemPos}) {
11352 return "";
11353 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011354 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011355 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011356
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011357 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11358 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011359 if($MemberPair_Pos_Rev eq "lost")
11360 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011361 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11362 { # base type match
11363 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011364 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011365 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11366 { # exact type match
11367 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011369 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11370 { # size match
11371 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011372 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011373 if(isReserved($Pair_Name))
11374 { # reserved fields
11375 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011376 }
11377 }
11378 return "";
11379}
11380
11381sub isLastElem($$)
11382{
11383 my ($Pos, $TypeRef) = @_;
11384 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011385 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011386 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11387 return 1;
11388 }
11389 elsif($Name=~/END|NLIMITS\Z/)
11390 { # __RLIMIT_NLIMITS
11391 return 1;
11392 }
11393 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11394 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11395 { # NImageFormats, NColorRoles
11396 return 1;
11397 }
11398 return 0;
11399}
11400
11401sub nonComparable($$)
11402{
11403 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011404
11405 my $N1 = $T1->{"Name"};
11406 my $N2 = $T2->{"Name"};
11407
11408 $N1=~s/\A(struct|union|enum) //;
11409 $N2=~s/\A(struct|union|enum) //;
11410
11411 if($N1 ne $N2
11412 and not isAnon($N1)
11413 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011414 { # different names
11415 if($T1->{"Type"} ne "Pointer"
11416 or $T2->{"Type"} ne "Pointer")
11417 { # compare base types
11418 return 1;
11419 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011420 if($N1!~/\Avoid\s*\*/
11421 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011422 {
11423 return 1;
11424 }
11425 }
11426 elsif($T1->{"Type"} ne $T2->{"Type"})
11427 { # different types
11428 if($T1->{"Type"} eq "Class"
11429 and $T2->{"Type"} eq "Struct")
11430 { # "class" to "struct"
11431 return 0;
11432 }
11433 elsif($T2->{"Type"} eq "Class"
11434 and $T1->{"Type"} eq "Struct")
11435 { # "struct" to "class"
11436 return 0;
11437 }
11438 else
11439 { # "class" to "enum"
11440 # "union" to "class"
11441 # ...
11442 return 1;
11443 }
11444 }
11445 return 0;
11446}
11447
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011448sub isOpaque($)
11449{
11450 my $T = $_[0];
11451 if(not defined $T->{"Memb"})
11452 {
11453 return 1;
11454 }
11455 return 0;
11456}
11457
11458sub removeVPtr($)
11459{ # support for old ABI dumps
11460 my $TPtr = $_[0];
11461 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11462 if($#Pos>=1)
11463 {
11464 foreach my $Pos (0 .. $#Pos-1)
11465 {
11466 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11467 }
11468 delete($TPtr->{"Memb"}{$#Pos});
11469 }
11470}
11471
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011472sub isPrivateABI($$)
11473{
11474 my ($TypeId, $LibVersion) = @_;
11475
11476 if($CheckPrivateABI) {
11477 return 0;
11478 }
11479
11480 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11481 return 1;
11482 }
11483
11484 return 0;
11485}
11486
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011487sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011488{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011489 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011490 return {} if(not $Type1_Id or not $Type2_Id);
11491
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011492 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011493 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011494 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011495 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011496
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011497 my %Type1 = get_Type($Type1_Id, 1);
11498 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011499 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011500 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011501 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011502
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011503 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11504 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011505
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011506 if(defined $UsedDump{1}{"DWARF"})
11507 {
11508 if($Type1_Pure{"Name"} eq "__unknown__"
11509 or $Type2_Pure{"Name"} eq "__unknown__")
11510 { # Error ABI dump
11511 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11512 }
11513 }
11514
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011515 if(isPrivateABI($Type1_Id, 1)) {
11516 return {};
11517 }
11518
11519 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11520 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11521
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011522 my %SubProblems = ();
11523
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011524 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11525 {
11526 if($Type1_Pure{"Type"}=~/Struct|Union/
11527 and $Type2_Pure{"Type"}=~/Struct|Union/)
11528 {
11529 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11530 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011531 if(not defined $UsedDump{1}{"DWARF"}
11532 and not defined $UsedDump{2}{"DWARF"})
11533 {
11534 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11535 "Target"=>$Type1_Pure{"Name"},
11536 "Type_Name"=>$Type1_Pure{"Name"} );
11537 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011538
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011539 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011540 }
11541 }
11542 }
11543
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011544 if(not $Type1_Pure{"Size"}
11545 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011546 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011547 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11548 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11549 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011550 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011551 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011552 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011553 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011554 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011555 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011556 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011557 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11558 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11559 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011560
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011561 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11562 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011563 }
11564
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011565 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11566 { # support for old ABI dumps
11567 # _vptr field added in 3.0
11568 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11569 {
11570 if(defined $Type2_Pure{"Memb"}
11571 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11572 {
11573 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11574 delete($Type2_Pure{"Memb"}{0});
11575 }
11576 else {
11577 removeVPtr(\%Type2_Pure);
11578 }
11579 }
11580 }
11581 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11582 {
11583 if(defined $Type1_Pure{"Memb"}
11584 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11585 {
11586 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11587 delete($Type1_Pure{"Memb"}{0});
11588 }
11589 else {
11590 removeVPtr(\%Type1_Pure);
11591 }
11592 }
11593 }
11594 }
11595
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011596 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11597 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011598
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011599 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011600 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11601 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011603 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11604 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011605 if($Base_1{"Name"} ne $Base_2{"Name"})
11606 {
11607 if(differentDumps("G")
11608 or differentDumps("V"))
11609 { # different GCC versions or different dumps
11610 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11611 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11612 # std::__va_list and __va_list
11613 $Base_1{"Name"}=~s/\A(\w+::)+//;
11614 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011615 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11616 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011618 }
11619 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11620 and $Base_1{"Name"} ne $Base_2{"Name"})
11621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011622 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011623 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011624 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011625 {
11626 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11627 "Target"=>$Typedef_1{"Name"},
11628 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011629 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11630 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11631 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011632 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11633 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011634
11635 if(defined $UsedDump{1}{"DWARF"})
11636 {
11637 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11638 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11639 { # Error ABI dump
11640 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11641 }
11642 }
11643
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011644 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011645 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011646 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11647 {
11648 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11649 "Target"=>$Typedef_1{"Name"},
11650 "Type_Name"=>$Typedef_1{"Name"},
11651 "Old_Value"=>$Base_1{"Name"},
11652 "New_Value"=>$Base_2{"Name"} );
11653 }
11654 else
11655 {
11656 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11657 "Target"=>$Typedef_1{"Name"},
11658 "Type_Name"=>$Typedef_1{"Name"},
11659 "Old_Value"=>$Base_1{"Name"},
11660 "New_Value"=>$Base_2{"Name"} );
11661 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011663 }
11664 }
11665 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11666 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011667 my $TT1 = $Type1_Pure{"Type"};
11668 my $TT2 = $Type2_Pure{"Type"};
11669
11670 if($TT1 ne $TT2
11671 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011672 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011673 my $Short1 = $Type1_Pure{"Name"};
11674 my $Short2 = $Type2_Pure{"Name"};
11675
11676 $Short1=~s/\A\Q$TT1\E //ig;
11677 $Short2=~s/\A\Q$TT2\E //ig;
11678
11679 if($Short1 eq $Short2)
11680 {
11681 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11682 "Target"=>$Type1_Pure{"Name"},
11683 "Type_Name"=>$Type1_Pure{"Name"},
11684 "Old_Value"=>lc($Type1_Pure{"Type"}),
11685 "New_Value"=>lc($Type2_Pure{"Type"}) );
11686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011687 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011688 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011689 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011690
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011691 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011692
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011693 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11694 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11695 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11696 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011697 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011698 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011699 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 {
11701 my $ProblemKind = "DataType_Size";
11702 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011703 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 {
11705 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11706 $ProblemKind = "Size_Of_Copying_Class";
11707 }
11708 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11709 {
11710 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11711 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11712 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011713 else
11714 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011715 # descreased size of allocable class
11716 # it has no special effects
11717 }
11718 }
11719 }
11720 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11721 "Target"=>$Type1_Pure{"Name"},
11722 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011723 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011724 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011725 }
11726 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011727 if(defined $Type1_Pure{"BaseType"}
11728 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011729 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011730 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11731 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011732 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011733 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11734 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011735 }
11736 }
11737 }
11738 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11739 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11740 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11741 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11742 { # detect removed and renamed fields
11743 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11744 next if(not $Member_Name);
11745 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);
11746 if($MemberPair_Pos eq "lost")
11747 {
11748 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11749 {
11750 if(isUnnamed($Member_Name))
11751 { # support for old-version dumps
11752 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011753 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 next;
11755 }
11756 }
11757 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11758 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011759 $RenamedField{$Member_Pos} = $RenamedTo;
11760 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011761 }
11762 else
11763 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011764 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011765 }
11766 }
11767 elsif($Type1_Pure{"Type"} eq "Enum")
11768 {
11769 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11770 next if($Member_Value1 eq "");
11771 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11772 if($MemberPair_Pos ne "lost")
11773 { # renamed
11774 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11775 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11776 if($MemberPair_Pos_Rev eq "lost")
11777 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011778 $RenamedField{$Member_Pos} = $RenamedTo;
11779 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011780 }
11781 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011782 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 }
11784 }
11785 else
11786 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011787 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011788 }
11789 }
11790 }
11791 else
11792 { # related
11793 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11794 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11795 }
11796 }
11797 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11798 { # detect added fields
11799 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11800 next if(not $Member_Name);
11801 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);
11802 if($MemberPair_Pos eq "lost")
11803 {
11804 if(isUnnamed($Member_Name))
11805 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011806 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011807 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011808 next;
11809 }
11810 }
11811 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11812 {
11813 if(not $RenamedField_Rev{$Member_Pos})
11814 { # added
11815 $AddedField{$Member_Pos}=1;
11816 }
11817 }
11818 }
11819 }
11820 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11821 { # detect moved fields
11822 my (%RelPos, %RelPosName, %AbsPos) = ();
11823 my $Pos = 0;
11824 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11825 { # relative positions in 1st version
11826 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11827 next if(not $Member_Name);
11828 if(not $RemovedField{$Member_Pos})
11829 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011830 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011831 $RelPosName{1}{$Pos} = $Member_Name;
11832 $AbsPos{1}{$Pos++} = $Member_Pos;
11833 }
11834 }
11835 $Pos = 0;
11836 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11837 { # relative positions in 2nd version
11838 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11839 next if(not $Member_Name);
11840 if(not $AddedField{$Member_Pos})
11841 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011842 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011843 $RelPosName{2}{$Pos} = $Member_Name;
11844 $AbsPos{2}{$Pos++} = $Member_Pos;
11845 }
11846 }
11847 foreach my $Member_Name (keys(%{$RelPos{1}}))
11848 {
11849 my $RPos1 = $RelPos{1}{$Member_Name};
11850 my $AbsPos1 = $NameToPosA{$Member_Name};
11851 my $Member_Name2 = $Member_Name;
11852 if(my $RenamedTo = $RenamedField{$AbsPos1})
11853 { # renamed
11854 $Member_Name2 = $RenamedTo;
11855 }
11856 my $RPos2 = $RelPos{2}{$Member_Name2};
11857 if($RPos2 ne "" and $RPos1 ne $RPos2)
11858 { # different relative positions
11859 my $AbsPos2 = $NameToPosB{$Member_Name2};
11860 if($AbsPos1 ne $AbsPos2)
11861 { # different absolute positions
11862 my $ProblemType = "Moved_Field";
11863 if(not isPublic(\%Type1_Pure, $AbsPos1))
11864 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011865 if($Level eq "Source") {
11866 next;
11867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011868 $ProblemType = "Moved_Private_Field";
11869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011870 if($Level eq "Binary"
11871 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011873 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011874 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011875 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011876 if($MemSize1 ne $MemSize2) {
11877 $ProblemType .= "_And_Size";
11878 }
11879 }
11880 if($ProblemType eq "Moved_Private_Field") {
11881 next;
11882 }
11883 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11884 "Target"=>$Member_Name,
11885 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011886 "Old_Value"=>$RPos1,
11887 "New_Value"=>$RPos2 );
11888 }
11889 }
11890 }
11891 }
11892 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011893 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011894 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11895 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011896 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011897 if(my $RenamedTo = $RenamedField{$Member_Pos})
11898 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011899 if(defined $Constants{2}{$Member_Name})
11900 {
11901 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11902 { # define OLD NEW
11903 next; # Safe
11904 }
11905 }
11906
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011907 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11908 {
11909 if(isPublic(\%Type1_Pure, $Member_Pos))
11910 {
11911 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11912 "Target"=>$Member_Name,
11913 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 "Old_Value"=>$Member_Name,
11915 "New_Value"=>$RenamedTo );
11916 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011917 elsif(isReserved($Member_Name))
11918 {
11919 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11920 "Target"=>$Member_Name,
11921 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011922 "Old_Value"=>$Member_Name,
11923 "New_Value"=>$RenamedTo );
11924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011925 }
11926 elsif($Type1_Pure{"Type"} eq "Enum")
11927 {
11928 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11929 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11930 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011931 "Old_Value"=>$Member_Name,
11932 "New_Value"=>$RenamedTo );
11933 }
11934 }
11935 elsif($RemovedField{$Member_Pos})
11936 { # removed
11937 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11938 {
11939 my $ProblemType = "Removed_Field";
11940 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011941 or isUnnamed($Member_Name))
11942 {
11943 if($Level eq "Source") {
11944 next;
11945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011946 $ProblemType = "Removed_Private_Field";
11947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011948 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011949 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 {
11951 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11952 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011953 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 +040011954 { # changed offset
11955 $ProblemType .= "_And_Layout";
11956 }
11957 }
11958 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11959 { # affected size
11960 $ProblemType .= "_And_Size";
11961 }
11962 }
11963 if($ProblemType eq "Removed_Private_Field") {
11964 next;
11965 }
11966 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11967 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011968 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011969 }
11970 elsif($Type2_Pure{"Type"} eq "Union")
11971 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011972 if($Level eq "Binary"
11973 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011974 {
11975 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11976 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011977 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011978 }
11979 else
11980 {
11981 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11982 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011983 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011984 }
11985 }
11986 elsif($Type1_Pure{"Type"} eq "Enum")
11987 {
11988 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11989 "Target"=>$Member_Name,
11990 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011991 "Old_Value"=>$Member_Name );
11992 }
11993 }
11994 else
11995 { # changed
11996 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11997 if($Type1_Pure{"Type"} eq "Enum")
11998 {
11999 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12000 next if($Member_Value1 eq "");
12001 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12002 next if($Member_Value2 eq "");
12003 if($Member_Value1 ne $Member_Value2)
12004 {
12005 my $ProblemType = "Enum_Member_Value";
12006 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12007 $ProblemType = "Enum_Last_Member_Value";
12008 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012009 if($SkipConstants{1}{$Member_Name}) {
12010 $ProblemType = "Enum_Private_Member_Value";
12011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012012 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12013 "Target"=>$Member_Name,
12014 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012015 "Old_Value"=>$Member_Value1,
12016 "New_Value"=>$Member_Value2 );
12017 }
12018 }
12019 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12020 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012021 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12022 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12023
12024 if($Access1 ne "private"
12025 and $Access2 eq "private")
12026 {
12027 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12028 "Target"=>$Member_Name,
12029 "Type_Name"=>$Type1_Pure{"Name"});
12030 }
12031 elsif($Access1 ne "protected"
12032 and $Access1 ne "private"
12033 and $Access2 eq "protected")
12034 {
12035 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12036 "Target"=>$Member_Name,
12037 "Type_Name"=>$Type1_Pure{"Name"});
12038 }
12039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012040 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12041 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012042 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12044 $SizeV1 = $BSize1;
12045 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012046 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012047 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12048 $SizeV2 = $BSize2;
12049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012050 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12051 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012052 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012053 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012054 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012055 {
12056 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12057 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12058 { # field size change (including anon-structures and unions)
12059 # - same types
12060 # - unnamed types
12061 # - bitfields
12062 my $ProblemType = "Field_Size";
12063 if(not isPublic(\%Type1_Pure, $Member_Pos)
12064 or isUnnamed($Member_Name))
12065 { # should not be accessed by applications, goes to "Low Severity"
12066 # example: "abidata" members in GStreamer types
12067 $ProblemType = "Private_".$ProblemType;
12068 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012069 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 +040012070 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012071 if($Type2_Pure{"Type"} ne "Union"
12072 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012073 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012074 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 +040012075 { # changed offset
12076 $ProblemType .= "_And_Layout";
12077 }
12078 }
12079 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12080 $ProblemType .= "_And_Type_Size";
12081 }
12082 }
12083 if($ProblemType eq "Private_Field_Size")
12084 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012086 if($ProblemType eq "Field_Size")
12087 {
12088 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12089 { # Low severity
12090 $ProblemType = "Struct_Field_Size_Increased";
12091 }
12092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012093 if($ProblemType)
12094 { # register a problem
12095 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12096 "Target"=>$Member_Name,
12097 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012098 "Old_Size"=>$SizeV1,
12099 "New_Size"=>$SizeV2);
12100 }
12101 }
12102 }
12103 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12104 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12105 { # do NOT check bitfield type changes
12106 next;
12107 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012108 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012109 {
12110 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12111 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12112 {
12113 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12114 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012115 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012116 }
12117 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12118 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12119 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012120 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012121 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012122 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012123 }
12124 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012125 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12126 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012127 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012128 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12129 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012130
12131 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012132 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012133 or $ProblemType eq "Field_Type_And_Size"
12134 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012135 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012136 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012137 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012138 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012139 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012140 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012141 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012142 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012143 }
12144 }
12145 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12146 {
12147 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012148 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012149 }
12150 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012151 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012152 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012153 }
12154 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12155 {
12156 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012157 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012158 }
12159 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012160 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012161 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012162 }
12163 }
12164 }
12165
12166 if($Level eq "Source")
12167 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012169 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012170 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12171 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012172
12173 if($ProblemType eq "Field_Type")
12174 {
12175 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012176 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012177 }
12178 }
12179 }
12180 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012181
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012182 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012183 {
12184 my $ProblemType_Init = $ProblemType;
12185 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012186 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012187 if(not isPublic(\%Type1_Pure, $Member_Pos)
12188 or isUnnamed($Member_Name)) {
12189 $ProblemType = "Private_".$ProblemType;
12190 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012191 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 +040012192 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012193 if($Type2_Pure{"Type"} ne "Union"
12194 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012195 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012196 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 +040012197 { # changed offset
12198 $ProblemType .= "_And_Layout";
12199 }
12200 }
12201 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12202 $ProblemType .= "_And_Type_Size";
12203 }
12204 }
12205 }
12206 else
12207 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012208 # TODO: Private_Field_Type rule?
12209
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012210 if(not isPublic(\%Type1_Pure, $Member_Pos)
12211 or isUnnamed($Member_Name)) {
12212 next;
12213 }
12214 }
12215 if($ProblemType eq "Private_Field_Type_And_Size")
12216 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012217 }
12218 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12219 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012220 "Type_Name"=>$Type1_Pure{"Name"});
12221
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012222 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012223 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012224 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 }
12226 }
12227 if(not isPublic(\%Type1_Pure, $Member_Pos))
12228 { # do NOT check internal type changes
12229 next;
12230 }
12231 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012232 { # checking member type changes
12233 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12234
12235 my %DupProblems = ();
12236
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012237 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012238 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012239 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012240 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012241 if(not defined $AllAffected)
12242 {
12243 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12244 next;
12245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012246 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012247
12248 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12249 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12250
12251 if(not defined $AllAffected)
12252 {
12253 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012254 }
12255 }
12256 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012257
12258 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012259 }
12260 }
12261 }
12262 }
12263 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12264 { # checking added members, public and private
12265 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12266 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012267 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 if($AddedField{$Member_Pos})
12269 { # added
12270 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12271 {
12272 my $ProblemType = "Added_Field";
12273 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012274 or isUnnamed($Member_Name))
12275 {
12276 if($Level eq "Source") {
12277 next;
12278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012279 $ProblemType = "Added_Private_Field";
12280 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012281 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012282 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 {
12284 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12285 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012286 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 +040012287 { # changed offset
12288 $ProblemType .= "_And_Layout";
12289 }
12290 }
12291 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12292 $ProblemType .= "_And_Size";
12293 }
12294 }
12295 if($ProblemType eq "Added_Private_Field")
12296 { # skip added private fields
12297 next;
12298 }
12299 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12300 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012301 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 }
12303 elsif($Type2_Pure{"Type"} eq "Union")
12304 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012305 if($Level eq "Binary"
12306 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012307 {
12308 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12309 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012310 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012311 }
12312 else
12313 {
12314 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12315 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012316 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 }
12318 }
12319 elsif($Type2_Pure{"Type"} eq "Enum")
12320 {
12321 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12322 next if($Member_Value eq "");
12323 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12324 "Target"=>$Member_Name,
12325 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012326 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012327 }
12328 }
12329 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012330
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012331 if($Type1_Pure{"Type"} eq "FuncPtr")
12332 {
12333 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12334 {
12335 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12336 next;
12337 }
12338
12339 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12340 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12341
12342 my $PName = "p".$PPos;
12343
12344 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12345 my %DupProblems = ();
12346
12347 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12348 {
12349 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12350 {
12351 if(not defined $AllAffected)
12352 {
12353 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12354 next;
12355 }
12356 }
12357
12358 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12359 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12360
12361 if(not defined $AllAffected)
12362 {
12363 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12364 }
12365 }
12366 }
12367
12368 %DupProblems = ();
12369 }
12370 }
12371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012372 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012373 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012374}
12375
12376sub isUnnamed($) {
12377 return $_[0]=~/\Aunnamed\d+\Z/;
12378}
12379
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012380sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012381{
12382 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012383 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12384 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12385 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012388 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012389 }
12390 return $TypeName;
12391}
12392
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012393sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012395 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012396 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12398 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012400 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12401 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012402 return () if(not $Type{"Type"});
12403 if($Type{"Type"} ne $Type_Type)
12404 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012405 return () if(not $Type{"BaseType"});
12406 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012407 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012408 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012409 return %Type;
12410}
12411
12412my %TypeSpecAttributes = (
12413 "Const" => 1,
12414 "Volatile" => 1,
12415 "ConstVolatile" => 1,
12416 "Restrict" => 1,
12417 "Typedef" => 1
12418);
12419
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012420sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012421{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012422 my ($TypeId, $Info) = @_;
12423 if(not $TypeId or not $Info
12424 or not $Info->{$TypeId}) {
12425 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012426 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012427 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12428 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12429 }
12430 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012431 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012433 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012435 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 return %Type;
12437}
12438
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012439sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012441 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012442 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012443 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12444 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012445 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012446 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12447 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012448 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12449 my $PLevel = 0;
12450 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12451 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012453 return $PLevel if(not $Type{"BaseType"});
12454 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12455 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12456 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457}
12458
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012459sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012461 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012462 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12464 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012465 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012466 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12467 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012468 return %Type if(not $Type{"BaseType"});
12469 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012470 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012471 return %Type;
12472}
12473
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012474sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012475{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012476 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012477 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012478 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12479 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012480 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 my $Qual = "";
12482 if($Type{"Type"} eq "Pointer") {
12483 $Qual .= "*";
12484 }
12485 elsif($Type{"Type"} eq "Ref") {
12486 $Qual .= "&";
12487 }
12488 elsif($Type{"Type"} eq "ConstVolatile") {
12489 $Qual .= "const volatile";
12490 }
12491 elsif($Type{"Type"} eq "Const"
12492 or $Type{"Type"} eq "Volatile"
12493 or $Type{"Type"} eq "Restrict") {
12494 $Qual .= lc($Type{"Type"});
12495 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012496 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012497 return $BQual.$Qual;
12498}
12499
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012500sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012502 my ($TypeId, $Info) = @_;
12503 if(not $TypeId or not $Info
12504 or not $Info->{$TypeId}) {
12505 return ();
12506 }
12507 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012508 return %Type if(not $Type{"BaseType"});
12509 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012510 {
12511 if($Info->{$BTid}) {
12512 return %{$Info->{$BTid}};
12513 }
12514 else { # something is going wrong
12515 return ();
12516 }
12517 }
12518 else {
12519 return %Type;
12520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521}
12522
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012523sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012524{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012525 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012526 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012527 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12528 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529}
12530
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012531sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012532{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012533 my $Symbol = $_[0];
12534 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12535}
12536
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012537sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012538 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12539}
12540
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012541sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012542{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012543 my ($SInfo, $LibVersion) = @_;
12544
12545 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012546 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012547 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012548 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012549 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012550 return 1;
12551 }
12552 }
12553 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012554 if(my $ShortName = $SInfo->{"ShortName"})
12555 {
12556 if(index($ShortName,"<")!=-1
12557 and index($ShortName,">")!=-1) {
12558 return 1;
12559 }
12560 }
12561
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012562 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012563}
12564
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012565sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012566{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012567 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012568 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012569 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012570 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012571 { # class specialization
12572 return 1;
12573 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012574 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 { # method specialization
12576 return 1;
12577 }
12578 }
12579 return 0;
12580}
12581
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012582sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012583{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012584 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012585
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012586 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587 { # non-public global data
12588 return 0;
12589 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012590
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012591 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012592 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012593 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012594 }
12595
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012596 if($Symbol=~/\A_Z/)
12597 {
12598 if($Symbol=~/[CD][3-4]E/) {
12599 return 0;
12600 }
12601 }
12602
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012603 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 { # support for old ABI dumps in --headers-only mode
12605 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12606 {
12607 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12608 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012609 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012610 if(not $PType or $PType eq "Unknown") {
12611 return 0;
12612 }
12613 }
12614 }
12615 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012616 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012618 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012620 if($SkipSymbols{$LibVersion}{$Symbol})
12621 { # user defined symbols to ignore
12622 return 0;
12623 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012624
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012625 if($SymbolsListPath and not $SymbolsList{$Symbol})
12626 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012627 if(not $TargetHeadersPath or not $Header
12628 or not is_target_header($Header, 1))
12629 { # -symbols-list | -headers-list
12630 return 0;
12631 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012632 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012633
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012634 if($AppPath and not $SymbolsList_App{$Symbol})
12635 { # user defined symbols (in application)
12636 return 0;
12637 }
12638
12639 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12640
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012641 if($ClassId)
12642 {
12643 if(not isTargetType($ClassId, $LibVersion)) {
12644 return 0;
12645 }
12646 }
12647
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12649 if(not $NameSpace and $ClassId)
12650 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012651 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 }
12653 if($NameSpace)
12654 { # user defined namespaces to ignore
12655 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12656 return 0;
12657 }
12658 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12659 { # nested namespaces
12660 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12661 return 0;
12662 }
12663 }
12664 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012665 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012666 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012667 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012668 { # --skip-headers or <skip_headers> (not <skip_including>)
12669 if($Skip==1) {
12670 return 0;
12671 }
12672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012673 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012674 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012675 { # user defined types
12676 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12677
12678 if(not $TypesList{$CName})
12679 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012680 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12681 {
12682 $CName=~s/\A\Q$NS\E\:\://g;
12683 }
12684
12685 if(not $TypesList{$CName})
12686 {
12687 my $Found = 0;
12688
12689 while($CName=~s/\:\:.+?\Z//)
12690 {
12691 if($TypesList{$CName})
12692 {
12693 $Found = 1;
12694 last;
12695 }
12696 }
12697
12698 if(not $Found) {
12699 return 0;
12700 }
12701 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012702 }
12703 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012704
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012705 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12706 { # non-target symbols
12707 return 0;
12708 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012709 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012710 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012711 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12712 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012713 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012714 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12715 { # inline virtual methods
12716 if($Type=~/InlineVirt/) {
12717 return 1;
12718 }
12719 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12720 if(not $Allocable)
12721 { # check bases
12722 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12723 {
12724 if(not isCopyingClass($DCId, $LibVersion))
12725 { # exists a derived class without default c-tor
12726 $Allocable=1;
12727 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012729 }
12730 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012731 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012732 return 0;
12733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012734 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012735 else
12736 { # inline non-virtual methods
12737 return 0;
12738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012740 }
12741 }
12742 return 1;
12743}
12744
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012745sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012746{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012747 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012748 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12749 {
12750 if(link_symbol($Symbol, 1, "+Deps"))
12751 { # linker can find a new symbol
12752 # in the old-version library
12753 # So, it's not a new symbol
12754 next;
12755 }
12756 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012757 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758 next;
12759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 }
12762}
12763
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012764sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012765{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012766 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012767 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12768 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012769 if(link_symbol($Symbol, 2, "+Deps"))
12770 { # linker can find an old symbol
12771 # in the new-version library
12772 next;
12773 }
12774 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012775 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012776 next;
12777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012778 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 }
12780}
12781
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012782sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012783{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012784 my $Level = $_[0];
12785 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012786 { # checking added symbols
12787 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012788 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012789 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012790 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012792 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012793 { # checking removed symbols
12794 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012795 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012796 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 { # skip v-tables for templates, that should not be imported by applications
12798 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012799 if(my $CName = $VTableClass{$Symbol})
12800 {
12801 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12802 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012803 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012804 next;
12805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012807
12808 if($SkipSymbols{1}{$Symbol})
12809 { # user defined symbols to ignore
12810 next;
12811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012812 }
12813 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012814 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012815 }
12816 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12817 { # symbols for pure virtual methods cannot be called by clients
12818 next;
12819 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012820 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012821 }
12822}
12823
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012824sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012826 my ($LibVersion, $V) = @_;
12827 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12828 return $Cache{"checkDump"}{$LibVersion}{$V};
12829 }
12830 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831}
12832
12833sub detectAdded_H($)
12834{
12835 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012836 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12837 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012838 if($Level eq "Source")
12839 { # remove symbol version
12840 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12841 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012842
12843 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12844 { # skip artificial constructors
12845 next;
12846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012847 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012848 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12849 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 next;
12851 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012852 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012853 next;
12854 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012855 if(not defined $CompleteSignature{1}{$Symbol}
12856 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12857 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012858 if($UsedDump{2}{"SrcBin"})
12859 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012860 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012861 { # support for old and different (!) ABI dumps
12862 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12863 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012864 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012865 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012866 {
12867 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12868 {
12869 if($Lang eq "C")
12870 { # support for old ABI dumps: missed extern "C" functions
12871 next;
12872 }
12873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012874 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012875 else
12876 {
12877 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012878 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012879 next;
12880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012881 }
12882 }
12883 }
12884 }
12885 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012886 }
12887 }
12888}
12889
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012890sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012891{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012892 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12894 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012895 if($Level eq "Source")
12896 { # remove symbol version
12897 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12898 $Symbol=$SN;
12899 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012900 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12901 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012902 next;
12903 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012904 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012905 next;
12906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012907 if(not defined $CompleteSignature{2}{$Symbol}
12908 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012909 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012910 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012911 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012912 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012913 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12915 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012917 if($CheckHeadersOnly)
12918 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012919 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12920 {
12921 if($Lang eq "C")
12922 { # support for old ABI dumps: missed extern "C" functions
12923 next;
12924 }
12925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 else
12928 {
12929 if(not link_symbol($Symbol, 1, "-Deps"))
12930 { # skip removed inline symbols
12931 next;
12932 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012933 }
12934 }
12935 }
12936 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012937 if(not checkDump(1, "2.15"))
12938 {
12939 if($Symbol=~/_IT_E\Z/)
12940 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12941 next;
12942 }
12943 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012944 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12945 {
12946 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12947 {
12948 if(defined $Constants{2}{$Short})
12949 {
12950 my $Val = $Constants{2}{$Short}{"Value"};
12951 if(defined $Func_ShortName{2}{$Val})
12952 { # old name defined to new
12953 next;
12954 }
12955 }
12956 }
12957
12958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959 $RemovedInt{$Level}{$Symbol} = 1;
12960 if($Level eq "Source")
12961 { # search for a source-compatible equivalent
12962 setAlternative($Symbol, $Level);
12963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012964 }
12965 }
12966}
12967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012968sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012969{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012970 my $Level = $_[0];
12971 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012972 { # checking added symbols
12973 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012974 next if($CompleteSignature{2}{$Symbol}{"Private"});
12975 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012976 if($Level eq "Binary")
12977 {
12978 if($CompleteSignature{2}{$Symbol}{"InLine"})
12979 {
12980 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12981 { # skip inline non-virtual functions
12982 next;
12983 }
12984 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 }
12986 else
12987 { # Source
12988 if($SourceAlternative_B{$Symbol}) {
12989 next;
12990 }
12991 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012992 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012993 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012994 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012995 { # checking removed symbols
12996 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012997 next if($CompleteSignature{1}{$Symbol}{"Private"});
12998 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012999 if($Level eq "Binary")
13000 {
13001 if($CompleteSignature{1}{$Symbol}{"InLine"})
13002 {
13003 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13004 { # skip inline non-virtual functions
13005 next;
13006 }
13007 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013008 }
13009 else
13010 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013011 if(my $Alt = $SourceAlternative{$Symbol})
13012 {
13013 if(defined $CompleteSignature{1}{$Alt}
13014 and $CompleteSignature{1}{$Symbol}{"Const"})
13015 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013016 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013017 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013018 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013019 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013020 }
13021 else
13022 { # do NOT show removed symbol
13023 next;
13024 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013025 }
13026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013027 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013028 }
13029}
13030
13031sub addParamNames($)
13032{
13033 my $LibraryVersion = $_[0];
13034 return if(not keys(%AddIntParams));
13035 my $SecondVersion = $LibraryVersion==1?2:1;
13036 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13037 {
13038 next if(not keys(%{$AddIntParams{$Interface}}));
13039 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013040 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013041 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13042 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013043 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13045 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13046 {
13047 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13048 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13049 }
13050 }
13051 else {
13052 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13053 }
13054 }
13055 }
13056 }
13057}
13058
13059sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013060{ # detect changed typedefs to show
13061 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013062 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13063 {
13064 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013065 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13066 if(not $BName1 or isAnon($BName1)) {
13067 next;
13068 }
13069 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13070 if(not $BName2 or isAnon($BName2)) {
13071 next;
13072 }
13073 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013074 $ChangedTypedef{$Typedef} = 1;
13075 }
13076 }
13077}
13078
13079sub get_symbol_suffix($$)
13080{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013081 my ($Symbol, $Full) = @_;
13082 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013083 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013084 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013085 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 if(not $Full) {
13087 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13088 }
13089 return $Suffix;
13090}
13091
13092sub get_symbol_prefix($$)
13093{
13094 my ($Symbol, $LibVersion) = @_;
13095 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13096 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13097 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013098 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013099 }
13100 return $ShortName;
13101}
13102
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013103sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013104{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013105 my $Symbol = $_[0];
13106 my $PSymbol = $Symbol;
13107 if(not defined $CompleteSignature{2}{$PSymbol}
13108 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13109 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13110 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013111 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013112 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013113 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013114 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013115 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13116 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013117 {
13118 if(defined $CompleteSignature{2}{$PSymbol}
13119 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13120 {
13121 $SourceAlternative{$Symbol} = $PSymbol;
13122 $SourceAlternative_B{$PSymbol} = $Symbol;
13123 if(not defined $CompleteSignature{1}{$PSymbol}
13124 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13125 $SourceReplacement{$Symbol} = $PSymbol;
13126 }
13127 }
13128 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013129 }
13130 else
13131 {
13132 foreach my $Sp ("KV", "VK", "K", "V")
13133 {
13134 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13135 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13136 {
13137 if(defined $CompleteSignature{2}{$PSymbol}
13138 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13139 {
13140 $SourceAlternative{$Symbol} = $PSymbol;
13141 $SourceAlternative_B{$PSymbol} = $Symbol;
13142 if(not defined $CompleteSignature{1}{$PSymbol}
13143 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13144 $SourceReplacement{$Symbol} = $PSymbol;
13145 }
13146 }
13147 }
13148 $PSymbol = $Symbol;
13149 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013150 }
13151 }
13152 }
13153 return "";
13154}
13155
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013156sub getSymKind($$)
13157{
13158 my ($Symbol, $LibVersion) = @_;
13159 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13160 {
13161 return "Global_Data";
13162 }
13163 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13164 {
13165 return "Method";
13166 }
13167 return "Function";
13168}
13169
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013170sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013171{
13172 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013173 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013174
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175 mergeBases($Level);
13176
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013178 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013179 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013181 next;
13182 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013183 if(defined $CompleteSignature{1}{$Symbol}
13184 and $CompleteSignature{1}{$Symbol}{"Header"})
13185 { # double-check added symbol
13186 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013188 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013189 next;
13190 }
13191 if($Symbol=~/\A(_Z|\?)/)
13192 { # C++
13193 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13194 }
13195 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13196 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013197 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13198 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013199 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013200 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013201 {
13202 if($TName_Tid{1}{$AffectedClass_Name})
13203 { # class should exist in previous version
13204 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13205 { # old v-table is NOT copied by old applications
13206 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13207 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013208 "Target"=>get_Signature($Symbol, 2),
13209 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013210 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013213 }
13214 }
13215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13217 { # check all removed exported symbols
13218 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013219 next;
13220 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013221 if(defined $CompleteSignature{2}{$Symbol}
13222 and $CompleteSignature{2}{$Symbol}{"Header"})
13223 { # double-check removed symbol
13224 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013225 }
13226 if($CompleteSignature{1}{$Symbol}{"Private"})
13227 { # skip private methods
13228 next;
13229 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013230 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 next;
13232 }
13233 $CheckedSymbols{$Level}{$Symbol} = 1;
13234 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13235 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013236 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13237 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013239 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13240 {
13241 if($TName_Tid{2}{$AffectedClass_Name})
13242 { # class should exist in newer version
13243 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13244 { # old v-table is NOT copied by old applications
13245 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13246 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013247 "Target"=>get_Signature($OverriddenMethod, 1),
13248 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013249 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
13253 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013254 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013255 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013257 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013258 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013259 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013261 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013263 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 {
13265 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13266 "Target"=>$tr_name{$Symbol},
13267 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013268 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013270 else
13271 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013272 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013273 "Target"=>$tr_name{$Symbol},
13274 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013275 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013276 }
13277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013278 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013280 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013281 {
13282 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13283 "Target"=>$tr_name{$Symbol},
13284 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013285 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013286 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013287 else
13288 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013289 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013290 "Target"=>$tr_name{$Symbol},
13291 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013292 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013293 }
13294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013295 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13296 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13297 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13298 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13299 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013300 {
13301 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013302 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 $ProblemType = "Global_Data_Symbol_Changed_Type";
13304 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013305 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13306 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013307 "Old_Type"=>$RTName1,
13308 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013310 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 }
13312 }
13313 }
13314 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013315 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013316 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013317 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013318 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013321 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013322 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13323 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013324 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013325 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013327 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013328 }
13329 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013330 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13331 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013332 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013333 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013334 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013335 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013336 }
13337 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013338 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013340 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013341 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013342 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013345 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013346 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013347 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013348 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013349 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013355 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013359 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013360 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013362 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013363 { # "volatile" to non-"volatile"
13364
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013365 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013371 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013372 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013374 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013377 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013378 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13383 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013386 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 }
13388 }
13389 }
13390 }
13391 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13393 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013394 $CurrentSymbol = $Symbol;
13395
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013396 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13397 if($Level eq "Source")
13398 { # remove symbol version
13399 $Symbol=$SN;
13400 }
13401 else
13402 { # Binary
13403 if(not $SV)
13404 { # symbol without version
13405 if(my $VSym = $SymVer{1}{$Symbol})
13406 { # the symbol is linked with versioned symbol
13407 if($CompleteSignature{2}{$VSym}{"MnglName"})
13408 { # show report for symbol@ver only
13409 next;
13410 }
13411 elsif(not link_symbol($VSym, 2, "-Deps"))
13412 { # changed version: sym@v1 to sym@v2
13413 # do NOT show report for symbol
13414 next;
13415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013416 }
13417 }
13418 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013419 my $PSymbol = $Symbol;
13420 if($Level eq "Source"
13421 and my $S = $SourceReplacement{$Symbol})
13422 { # take a source-compatible replacement function
13423 $PSymbol = $S;
13424 }
13425 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 { # private symbols
13427 next;
13428 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013429 if(not defined $CompleteSignature{1}{$Symbol}
13430 or not defined $CompleteSignature{2}{$PSymbol})
13431 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013432 next;
13433 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013434 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13435 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13436 { # no mangled name
13437 next;
13438 }
13439 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13440 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013441 { # without a header
13442 next;
13443 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013444
13445 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13446 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13447 { # became pure
13448 next;
13449 }
13450 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13451 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13452 { # became non-pure
13453 next;
13454 }
13455
13456 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13457 { # exported, target, inline virtual and pure virtual
13458 next;
13459 }
13460 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13461 { # exported, target, inline virtual and pure virtual
13462 next;
13463 }
13464
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013465 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013466 {
13467 if($CompleteSignature{1}{$Symbol}{"Data"}
13468 and $CompleteSignature{2}{$PSymbol}{"Data"})
13469 {
13470 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13471 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13472 if(defined $Value1)
13473 {
13474 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13475 if(defined $Value2)
13476 {
13477 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13478 if($Value1 ne $Value2)
13479 {
13480 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13481 "Old_Value"=>$Value1,
13482 "New_Value"=>$Value2,
13483 "Target"=>get_Signature($Symbol, 1) );
13484 }
13485 }
13486 }
13487 }
13488 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013489
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013490 if($CompleteSignature{2}{$PSymbol}{"Private"})
13491 {
13492 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13493 "Target"=>get_Signature_M($PSymbol, 2) );
13494 }
13495 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13496 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13497 {
13498 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13499 "Target"=>get_Signature_M($PSymbol, 2) );
13500 }
13501 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13502 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13503 {
13504 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13505 "Target"=>get_Signature_M($PSymbol, 2) );
13506 }
13507
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013508 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013509 mergeVirtualTables($Symbol, $Level);
13510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013511 if($COMPILE_ERRORS)
13512 { # if some errors occurred at the compiling stage
13513 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013515 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013516 { # missed information about parameters in newer version
13517 next;
13518 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013519 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013520 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013521 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 next;
13523 }
13524 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013525 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013526 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013527 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013528 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13529 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13531 "Target"=>get_Signature($Symbol, 1)
13532 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013534 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013535 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13536 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013537 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 "Target"=>get_Signature($Symbol, 1)
13539 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013540 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013541 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13542 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013543 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013544 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013545 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013546 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13547 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13548 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013549 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013550 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013551 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13552 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013553 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013554 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013555 my $ProblemType = "Virtual_Method_Position";
13556 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13557 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013558 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013559 if(isUsedClass($Class_Id, 1, $Level))
13560 {
13561 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013562 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013564 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13565 next;
13566 }
13567 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013568 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013569 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13570 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013571 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013573 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013575 }
13576 }
13577 }
13578 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013579 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13580 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013581 { # do NOT check type changes in pure virtuals
13582 next;
13583 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013584 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013585 if($Symbol=~/\A(_Z|\?)/
13586 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013588 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013590 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 }
13592 }
13593 else
13594 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013595 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013597 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013598 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13599 last if($PType2_Name eq "...");
13600 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13601 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013602 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013603 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013605 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13606 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013607 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13608 $ParamPos_Prev = "lost";
13609 }
13610 }
13611 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013612 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013613 }
13614 if($ParamPos_Prev eq "lost")
13615 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013616 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013617 {
13618 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013619 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013620 $ProblemType = "Added_Unnamed_Parameter";
13621 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013622 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013624 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013625 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013626 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 }
13628 else
13629 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013630 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013631 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013632 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013633 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13634 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013636 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013637 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013638 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013640 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013641 "Param_Type"=>$PType2_Name,
13642 "Old_Value"=>$PName_Old,
13643 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013644 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 }
13646 }
13647 else
13648 {
13649 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013650 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013651 $ProblemType = "Added_Middle_Unnamed_Parameter";
13652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013653 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013654 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013655 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013656 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013657 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013658 }
13659 }
13660 }
13661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013662 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013664 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013665 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013667 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013668 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013669 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013670 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013671 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13672 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013673 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013674 }
13675 }
13676 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013677 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013679 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013680 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13681 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013682 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13683 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013685 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013687 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13688 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013689 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13690 $ParamPos_New = "lost";
13691 }
13692 }
13693 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013694 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 }
13696 if($ParamPos_New eq "lost")
13697 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013698 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013699 {
13700 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013701 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013702 $ProblemType = "Removed_Unnamed_Parameter";
13703 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013704 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013705 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013706 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013707 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013708 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013710 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013711 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013712 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013713 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013714 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013716 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013717 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013718 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013720 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013721 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013722 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013723 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013724 "Old_Value"=>$PName,
13725 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013726 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 }
13728 }
13729 else
13730 {
13731 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013732 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013733 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13734 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013735 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013736 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013737 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013738 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013739 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013740 }
13741 }
13742 }
13743 }
13744 }
13745 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013746 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13747 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013748 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013749
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013750 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013751 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013752 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13753 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013754 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013755
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013756 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013757 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013758 if($SubProblemType eq "Return_Type_And_Size") {
13759 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13760 }
13761 elsif($SubProblemType eq "Return_Type_Format") {
13762 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13763 }
13764 else {
13765 $ProblemTypes{"Global_Data_Type"} = 1;
13766 }
13767
13768 # quals
13769 if($SubProblemType eq "Return_Type"
13770 or $SubProblemType eq "Return_Type_And_Size"
13771 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013772 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013773 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13774 { # const to non-const
13775 if($RR==2) {
13776 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13777 }
13778 else {
13779 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13780 }
13781 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013782 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013783 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13784 { # non-const to const
13785 if($RA==2) {
13786 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13787 }
13788 else {
13789 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13790 }
13791 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013792 }
13793 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013794 }
13795 else
13796 {
13797 # quals
13798 if($SubProblemType eq "Return_Type"
13799 or $SubProblemType eq "Return_Type_And_Size"
13800 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013801 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013802 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013803 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013804 if(addedQual($Old_Value, $New_Value, "volatile"))
13805 {
13806 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13807 if($Level ne "Source"
13808 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13809 $ProblemTypes{"Return_Type"} = 1;
13810 }
13811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013813 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13814 {
13815 if($RA==2) {
13816 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13817 }
13818 else {
13819 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13820 }
13821 if($Level ne "Source"
13822 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13823 $ProblemTypes{"Return_Type"} = 1;
13824 }
13825 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013826 }
13827 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013828 if($Level eq "Binary"
13829 and not $CompleteSignature{1}{$Symbol}{"Data"})
13830 {
13831 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13832 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13833 { # if one of the architectures is unknown
13834 # then set other arhitecture to unknown too
13835 ($Arch1, $Arch2) = ("unknown", "unknown");
13836 }
13837 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013838 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013839 {
13840 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13841 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13842 }
13843 else
13844 {
13845 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13846 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13847 }
13848
13849 if($SubProblemType eq "Return_Type_Became_Void")
13850 {
13851 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13852 { # parameters stack has been affected
13853 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013854 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013855 }
13856 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013857 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013858 }
13859 }
13860 }
13861 elsif($SubProblemType eq "Return_Type_From_Void")
13862 {
13863 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13864 { # parameters stack has been affected
13865 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013866 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013867 }
13868 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013869 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013870 }
13871 }
13872 }
13873 elsif($SubProblemType eq "Return_Type"
13874 or $SubProblemType eq "Return_Type_And_Size"
13875 or $SubProblemType eq "Return_Type_Format")
13876 {
13877 if($Conv1{"Method"} ne $Conv2{"Method"})
13878 {
13879 if($Conv1{"Method"} eq "stack")
13880 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013881 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013882 }
13883 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013884 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013885 }
13886 }
13887 else
13888 {
13889 if($Conv1{"Method"} eq "reg")
13890 {
13891 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13892 {
13893 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013894 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013895 }
13896 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013897 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013898 }
13899 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013900 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013901 }
13902 }
13903 }
13904 }
13905 }
13906 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013907
13908 if(not keys(%ProblemTypes))
13909 { # default
13910 $ProblemTypes{$SubProblemType} = 1;
13911 }
13912
13913 foreach my $ProblemType (keys(%ProblemTypes))
13914 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013915 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013917 }
13918 if($ReturnType1_Id and $ReturnType2_Id)
13919 {
13920 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013921 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13922
13923 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013924
13925 if($CompleteSignature{1}{$Symbol}{"Data"})
13926 {
13927 if($Level eq "Binary")
13928 {
13929 if(get_PLevel($ReturnType1_Id, 1)==0)
13930 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013931 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013932 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013933
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013934 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13935 {
13936 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013937 {
13938 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13939 {
13940 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13941 last;
13942 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013943 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013944 }
13945 }
13946 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013947 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013948 {
13949 if(defined $GlobalDataObject{1}{$Symbol}
13950 and defined $GlobalDataObject{2}{$Symbol})
13951 {
13952 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13953 my $New_Size = $GlobalDataObject{2}{$Symbol};
13954 if($Old_Size!=$New_Size)
13955 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013956 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013957 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013958 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013959 }
13960 }
13961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013962 }
13963 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013964
13965 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013966 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013967 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013968 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013969 my $NewLocation = "retval";
13970 if($SubLocation and $SubLocation ne "retval") {
13971 $NewLocation = "retval->".$SubLocation;
13972 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013973 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13974 }
13975 }
13976
13977 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13978 {
13979 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13980 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013981 my $NewLocation = "retval";
13982 if($SubLocation and $SubLocation ne "retval") {
13983 $NewLocation = "retval->".$SubLocation;
13984 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013985 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013986 }
13987 }
13988 }
13989
13990 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013991 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13992 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13993 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013994 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013995 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013996 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13997 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013998 if($ThisPtr1_Id and $ThisPtr2_Id)
13999 {
14000 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014001 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14002 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014003 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014004 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014005 {
14006 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014007 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014008 }
14009 }
14010 }
14011 }
14012 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014013 if($Level eq "Binary") {
14014 mergeVTables($Level);
14015 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014016 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14017 $CheckedSymbols{$Level}{$Symbol} = 1;
14018 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014019}
14020
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014021sub rmQuals($$)
14022{
14023 my ($Value, $Qual) = @_;
14024 if(not $Qual) {
14025 return $Value;
14026 }
14027 if($Qual eq "all")
14028 { # all quals
14029 $Qual = "const|volatile|restrict";
14030 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014031 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014032 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014033 }
14034 return $Value;
14035}
14036
14037sub cmpBTypes($$$$)
14038{
14039 my ($T1, $T2, $V1, $V2) = @_;
14040 $T1 = uncover_typedefs($T1, $V1);
14041 $T2 = uncover_typedefs($T2, $V2);
14042 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14043}
14044
14045sub addedQual($$$)
14046{
14047 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014048 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014049}
14050
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014051sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014052{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014053 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014054 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014055}
14056
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014057sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014058{
14059 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14060 $Old_Value = uncover_typedefs($Old_Value, $V1);
14061 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014062
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014063 if($Old_Value eq $New_Value)
14064 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014065 return 0;
14066 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014067 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014068 { # without a qual
14069 return 0;
14070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014071 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014072 { # became non-qual
14073 return 1;
14074 }
14075 else
14076 {
14077 my @BQ1 = getQualModel($Old_Value, $Qual);
14078 my @BQ2 = getQualModel($New_Value, $Qual);
14079 foreach (0 .. $#BQ1)
14080 { # removed qual
14081 if($BQ1[$_]==1
14082 and $BQ2[$_]!=1)
14083 {
14084 return 2;
14085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014086 }
14087 }
14088 return 0;
14089}
14090
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014091sub getQualModel($$)
14092{
14093 my ($Value, $Qual) = @_;
14094 if(not $Qual) {
14095 return $Value;
14096 }
14097
14098 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014099 while($Value=~/(\w+)/)
14100 {
14101 my $W = $1;
14102
14103 if($W eq $Qual) {
14104 $Value=~s/\b$W\b/\@/g;
14105 }
14106 else {
14107 $Value=~s/\b$W\b//g;
14108 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014109 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014110
14111 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014112 $Value=~s/[^\*\&\w]+//g;
14113
14114 # modeling
14115 # int*const*const == 011
14116 # int**const == 001
14117 my @Model = ();
14118 my @Elems = split(/[\*\&]/, $Value);
14119 if(not @Elems) {
14120 return (0);
14121 }
14122 foreach (@Elems)
14123 {
14124 if($_ eq $Qual) {
14125 push(@Model, 1);
14126 }
14127 else {
14128 push(@Model, 0);
14129 }
14130 }
14131
14132 return @Model;
14133}
14134
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014135my %StringTypes = map {$_=>1} (
14136 "char*",
14137 "char const*"
14138);
14139
14140my %CharTypes = map {$_=>1} (
14141 "char",
14142 "char const"
14143);
14144
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014145sub showVal($$$)
14146{
14147 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014148 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014149 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014150 if(substr($Value, 0, 2) eq "_Z")
14151 {
14152 if(my $Unmangled = $tr_name{$Value}) {
14153 return $Unmangled;
14154 }
14155 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014156 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014157 { # strings
14158 return "\"$Value\"";
14159 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014160 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014161 { # characters
14162 return "\'$Value\'";
14163 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014164 if($Value eq "")
14165 { # other
14166 return "\'\'";
14167 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014168 return $Value;
14169}
14170
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014171sub getRegs($$$)
14172{
14173 my ($LibVersion, $Symbol, $Pos) = @_;
14174
14175 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14176 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014177 my %Regs = ();
14178 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14179 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014180 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014181 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14182 }
14183 }
14184
14185 return join(", ", sort keys(%Regs));
14186 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014187 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14188 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14189 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14190 {
14191 return "unknown";
14192 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014193
14194 return undef;
14195}
14196
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014197sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014198{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014199 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014200 if(not $Symbol) {
14201 return;
14202 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014203 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14204 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14205 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14206 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014207 if(not $PType1_Id
14208 or not $PType2_Id) {
14209 return;
14210 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014211
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014212 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014213 { # do not merge "this"
14214 if($PName1 eq "this" or $PName2 eq "this") {
14215 return;
14216 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014217 }
14218
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014219 my %Type1 = get_Type($PType1_Id, 1);
14220 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014221
14222 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14223
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014224 my %BaseType1 = get_BaseType($PType1_Id, 1);
14225 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014226
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014227 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014228
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014229 if($Level eq "Binary")
14230 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014231 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014232 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14233 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14234 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14235 {
14236 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014237 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014238 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014239 }
14240 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14241 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14242 {
14243 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014244 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014245 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014247 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014248
14249 if(defined $UsedDump{1}{"DWARF"}
14250 and defined $UsedDump{2}{"DWARF"})
14251 {
14252 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14253 {
14254 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14255 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014256
14257 if($Old_Regs ne "unknown"
14258 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014259 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014260 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014261 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014262 if($Old_Regs ne $New_Regs)
14263 {
14264 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14265 "Target"=>$PName1,
14266 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14267 "Old_Value"=>$Old_Regs,
14268 "New_Value"=>$New_Regs );
14269 }
14270 }
14271 elsif($Old_Regs and not $New_Regs)
14272 {
14273 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014274 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014275 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014276 "Old_Value"=>$Old_Regs );
14277 }
14278 elsif(not $Old_Regs and $New_Regs)
14279 {
14280 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14281 "Target"=>$PName1,
14282 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014283 "New_Value"=>$New_Regs );
14284 }
14285 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014286
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014287 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14288 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14289 {
14290 if($Old_Offset ne $New_Offset)
14291 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014292 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14293 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14294
14295 $Old_Offset = $Old_Offset - $Start1;
14296 $New_Offset = $New_Offset - $Start2;
14297
14298 if($Old_Offset ne $New_Offset)
14299 {
14300 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14301 "Target"=>$PName1,
14302 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14303 "Old_Value"=>$Old_Offset,
14304 "New_Value"=>$New_Offset );
14305 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014306 }
14307 }
14308 }
14309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014310 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014311 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14312 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014313 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014314 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014315 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14316 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014317 if(not checkDump(1, "2.13")
14318 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014319 { # support for old ABI dumps
14320 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014321 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014322 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014323 and $Value_Old eq "false" and $Value_New eq "0")
14324 { # int class::method ( bool p = 0 );
14325 # old ABI dumps: "false"
14326 # new ABI dumps: "0"
14327 $Value_Old = "0";
14328 }
14329 }
14330 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014331 if(not checkDump(1, "2.18")
14332 and checkDump(2, "2.18"))
14333 { # support for old ABI dumps
14334 if(not defined $Value_Old
14335 and substr($Value_New, 0, 2) eq "_Z") {
14336 $Value_Old = $Value_New;
14337 }
14338 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014339 if(defined $Value_Old)
14340 {
14341 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14342 if(defined $Value_New)
14343 {
14344 $Value_New = showVal($Value_New, $PType2_Id, 2);
14345 if($Value_Old ne $Value_New)
14346 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014347 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014348 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014349 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014350 "Old_Value"=>$Value_Old,
14351 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 }
14353 }
14354 else
14355 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014356 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014357 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014358 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014359 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014360 }
14361 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014362 elsif(defined $Value_New)
14363 {
14364 $Value_New = showVal($Value_New, $PType2_Id, 2);
14365 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14366 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014367 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014368 "New_Value"=>$Value_New );
14369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014370 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014371
14372 if($ChkRnmd)
14373 {
14374 if($PName1 and $PName2 and $PName1 ne $PName2
14375 and $PType1_Id!=-1 and $PType2_Id!=-1
14376 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14377 { # except unnamed "..." value list (Id=-1)
14378 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14379 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014380 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014381 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14382 "Old_Value"=>$PName1,
14383 "New_Value"=>$PName2,
14384 "New_Signature"=>get_Signature($Symbol, 2) );
14385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014388 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014389 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014391 foreach my $SubProblemType (keys(%SubProblems))
14392 { # add new problems, remove false alarms
14393 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14394 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014395
14396 # quals
14397 if($SubProblemType eq "Parameter_Type"
14398 or $SubProblemType eq "Parameter_Type_And_Size"
14399 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014401 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014402 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014403 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014404 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014405 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014406 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14407 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14408 }
14409 }
14410 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14411 {
14412 if(removedQual($Old_Value, $New_Value, "volatile")) {
14413 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 }
14415 }
14416 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14417 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14418 { # int to "int const"
14419 delete($SubProblems{$SubProblemType});
14420 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014421 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014422 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14423 { # "int const" to int
14424 delete($SubProblems{$SubProblemType});
14425 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014426 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14427 { # "const" to non-"const"
14428 if($RR==2) {
14429 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14430 }
14431 else {
14432 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14433 }
14434 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014435 }
14436 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014437
14438 if($Level eq "Source")
14439 {
14440 foreach my $SubProblemType (keys(%SubProblems))
14441 {
14442 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14443 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14444
14445 if($SubProblemType eq "Parameter_Type")
14446 {
14447 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14448 delete($SubProblems{$SubProblemType});
14449 }
14450 }
14451 }
14452 }
14453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014454 foreach my $SubProblemType (keys(%SubProblems))
14455 { # modify/register problems
14456 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14457 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014458 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14459 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014461 my $NewProblemType = $SubProblemType;
14462 if($Old_Value eq "..." and $New_Value ne "...")
14463 { # change from "..." to "int"
14464 if($ParamPos1==0)
14465 { # ISO C requires a named argument before "..."
14466 next;
14467 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014468 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 }
14470 elsif($New_Value eq "..." and $Old_Value ne "...")
14471 { # change from "int" to "..."
14472 if($ParamPos2==0)
14473 { # ISO C requires a named argument before "..."
14474 next;
14475 }
14476 $NewProblemType = "Parameter_Became_VaList";
14477 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014478 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014479 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014480 {
14481 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014482 if($Arch1 eq "unknown"
14483 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014484 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014485 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014486 ($Arch1, $Arch2) = ("unknown", "unknown");
14487 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014488 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014489 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014490 { # real
14491 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14492 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14493 }
14494 else
14495 { # model
14496 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14497 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14498 }
14499 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014501 if($Conv1{"Method"} eq "stack")
14502 {
14503 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14504 $NewProblemType = "Parameter_Type_And_Stack";
14505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014507 elsif($Conv1{"Method"} eq "reg")
14508 {
14509 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14510 $NewProblemType = "Parameter_Type_And_Register";
14511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 }
14513 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014514 elsif($Conv1{"Method"} ne "unknown"
14515 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014516 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014517 if($Conv1{"Method"} eq "stack") {
14518 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014519 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014520 elsif($Conv1{"Method"} eq "register") {
14521 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014522 }
14523 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014524 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14525 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014527 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014528 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014529 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014530 "New_Signature"=>get_Signature($Symbol, 2) );
14531 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014532 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014533
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014535
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014537 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14538 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014540 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014541 {
14542 my $NewProblemType = $SubProblemType;
14543 if($SubProblemType eq "DataType_Size")
14544 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014545 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014546 { # stack has been affected
14547 $NewProblemType = "DataType_Size_And_Stack";
14548 }
14549 }
14550 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014551 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 }
14553 }
14554}
14555
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014556sub find_ParamPair_Pos_byName($$$)
14557{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014558 my ($Name, $Symbol, $LibVersion) = @_;
14559 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014560 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014561 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14562 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014563 {
14564 return $ParamPos;
14565 }
14566 }
14567 return "lost";
14568}
14569
14570sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14571{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014572 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014574 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014575 {
14576 next if($Order eq "backward" and $ParamPos>$MediumPos);
14577 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014578 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14579 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014580 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014581 push(@Positions, $ParamPos);
14582 }
14583 }
14584 return @Positions;
14585}
14586
14587sub getTypeIdByName($$)
14588{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014589 my ($TypeName, $LibVersion) = @_;
14590 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014591}
14592
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014593sub diffTypes($$$)
14594{
14595 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14596 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14597 }
14598 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14599 { # skip recursive declarations
14600 return 0;
14601 }
14602
14603 pushType($_[0], $_[1], \@RecurTypes_Diff);
14604 my $Diff = diffTypes_I(@_);
14605 pop(@RecurTypes_Diff);
14606
14607 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14608}
14609
14610sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014611{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014612 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014613
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014614 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14615 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014616
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014617 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14618 { # equal types
14619 return 0;
14620 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014621 if($Type1_Pure{"Name"} eq "void")
14622 { # from void* to something
14623 return 0;
14624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625 if($Type1_Pure{"Name"}=~/\*/
14626 or $Type2_Pure{"Name"}=~/\*/)
14627 { # compared in detectTypeChange()
14628 return 0;
14629 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014630
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 my %FloatType = map {$_=>1} (
14632 "float",
14633 "double",
14634 "long double"
14635 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014636
14637 my $T1 = $Type1_Pure{"Type"};
14638 my $T2 = $Type2_Pure{"Type"};
14639
14640 if($T1 eq "Struct"
14641 and $T2 eq "Class")
14642 { # compare as data structures
14643 $T2 = "Struct";
14644 }
14645
14646 if($T1 eq "Class"
14647 and $T2 eq "Struct")
14648 { # compare as data structures
14649 $T1 = "Struct";
14650 }
14651
14652 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014654 if($T1 eq "Intrinsic"
14655 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014656 { # "int" to "enum"
14657 return 0;
14658 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014659 elsif($T2 eq "Intrinsic"
14660 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014661 { # "enum" to "int"
14662 return 0;
14663 }
14664 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014665 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014666 # ...
14667 return 1;
14668 }
14669 }
14670 else
14671 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014672 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014673 {
14674 if($FloatType{$Type1_Pure{"Name"}}
14675 or $FloatType{$Type2_Pure{"Name"}})
14676 { # "float" to "double"
14677 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014678 if($Level eq "Source")
14679 { # Safe
14680 return 0;
14681 }
14682 else {
14683 return 1;
14684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014685 }
14686 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014687 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014688 {
14689 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14690 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014691 if(not @Membs1
14692 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014693 { # private
14694 return 0;
14695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014696 if($#Membs1!=$#Membs2)
14697 { # different number of elements
14698 return 1;
14699 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014700 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014701 {
14702 foreach my $Pos (@Membs1)
14703 { # compare elements by name and value
14704 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14705 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14706 { # different names
14707 return 1;
14708 }
14709 }
14710 }
14711 else
14712 {
14713 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014714 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014715 if($Level eq "Source")
14716 {
14717 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14718 { # different names
14719 return 1;
14720 }
14721 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014722
14723 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14724 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14725
14726 if($MT1{"Name"} ne $MT2{"Name"}
14727 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14728 {
14729 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14730 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14731
14732 if($PL1 ne $PL2)
14733 { # different pointer level
14734 return 1;
14735 }
14736
14737 # compare base types
14738 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14739 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14740
14741 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14742 { # different types
14743 return 1;
14744 }
14745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014746 }
14747 }
14748 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014749 else
14750 {
14751 # TODO: arrays, etc.
14752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014753 }
14754 return 0;
14755}
14756
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014757sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014759 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014760 if(not $Type1_Id or not $Type2_Id) {
14761 return ();
14762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014763 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014764 my %Type1 = get_Type($Type1_Id, 1);
14765 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014766 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14767 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014768
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014769 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14770 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 +040014771
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014772 if(defined $UsedDump{1}{"DWARF"})
14773 {
14774 if($Type1_Pure{"Name"} eq "__unknown__"
14775 or $Type2_Pure{"Name"} eq "__unknown__"
14776 or $Type1_Base{"Name"} eq "__unknown__"
14777 or $Type2_Base{"Name"} eq "__unknown__")
14778 { # Error ABI dump
14779 return ();
14780 }
14781 }
14782
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014783 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14784 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014785 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14786 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14787 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14788 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14789 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14790 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14791 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014792 if($Type1{"Name"} eq $Type2{"Name"})
14793 {
14794 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14795 { # will be reported in mergeTypes() as typedef problem
14796 return ();
14797 }
14798 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14799 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14800 if(%Typedef_1 and %Typedef_2)
14801 {
14802 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14803 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14804 { # const Typedef
14805 return ();
14806 }
14807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014808 }
14809 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14810 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014811 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014812 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14813 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014814 {
14815 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14816 "Old_Value"=>$Type1_Base{"Name"},
14817 "New_Value"=>$Type2_Base{"Name"},
14818 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014819 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014820 }
14821 else
14822 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014823 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014824 { # format change
14825 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14826 "Old_Value"=>$Type1_Base{"Name"},
14827 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014828 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014829 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014830 }
14831 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14832 {
14833 %{$LocalProblems{$Prefix."_BaseType"}}=(
14834 "Old_Value"=>$Type1_Base{"Name"},
14835 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014836 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014837 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014838 }
14839 }
14840 }
14841 }
14842 elsif($Type1{"Name"} ne $Type2{"Name"})
14843 { # type change
14844 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14845 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014846 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014847 and $Type1_Pure{"Name"} eq "void")
14848 {
14849 %{$LocalProblems{"Return_Type_From_Void"}}=(
14850 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014851 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014853 elsif($Prefix eq "Return"
14854 and $Type2_Pure{"Name"} eq "void")
14855 {
14856 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14857 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014858 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014859 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 else
14861 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014862 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014863 and $Type1{"Size"} and $Type2{"Size"}
14864 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 {
14866 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14867 "Old_Value"=>$Type1{"Name"},
14868 "New_Value"=>$Type2{"Name"},
14869 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014870 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014871 }
14872 else
14873 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014874 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014875 { # format change
14876 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14877 "Old_Value"=>$Type1{"Name"},
14878 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014879 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014880 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014881 }
14882 elsif(tNameLock($Type1_Id, $Type2_Id))
14883 { # FIXME: correct this condition
14884 %{$LocalProblems{$Prefix."_Type"}}=(
14885 "Old_Value"=>$Type1{"Name"},
14886 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014887 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014888 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 }
14890 }
14891 }
14892 }
14893 }
14894 if($Type1_PLevel!=$Type2_PLevel)
14895 {
14896 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14897 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14898 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014899 if($Level eq "Source")
14900 {
14901 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014902 "Old_Value"=>$Type1_PLevel,
14903 "New_Value"=>$Type2_PLevel);
14904 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014905 else
14906 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014907 if($Type2_PLevel>$Type1_PLevel)
14908 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014909 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14910 "Old_Value"=>$Type1_PLevel,
14911 "New_Value"=>$Type2_PLevel);
14912 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014913 else
14914 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014915 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14916 "Old_Value"=>$Type1_PLevel,
14917 "New_Value"=>$Type2_PLevel);
14918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014919 }
14920 }
14921 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014922 if($Type1_Pure{"Type"} eq "Array"
14923 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 { # base_type[N] -> base_type[N]
14925 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014926 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 foreach my $SubProblemType (keys(%SubProblems))
14928 {
14929 $SubProblemType=~s/_Type/_BaseType/g;
14930 next if(defined $LocalProblems{$SubProblemType});
14931 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14932 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14933 }
14934 }
14935 }
14936 return %LocalProblems;
14937}
14938
14939sub tNameLock($$)
14940{
14941 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014942 my $Changed = 0;
14943 if(differentDumps("G"))
14944 { # different GCC versions
14945 $Changed = 1;
14946 }
14947 elsif(differentDumps("V"))
14948 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014949 if(not checkDump(1, "2.20")
14950 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014951 { # latest names update
14952 # 2.6: added restrict qualifier
14953 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014954 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014955 $Changed = 1;
14956 }
14957 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014958
14959 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14960 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14961
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014962 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14963 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14964
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014965 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014966 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014967 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014968 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014969 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014971 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014972 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014973 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014974 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014975 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14976 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14977 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014978 { # equal base types
14979 return 0;
14980 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014981
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014982 if(not checkDump(1, "2.13")
14983 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014984 { # broken array names in ABI dumps < 2.13
14985 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014986 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014987 return 0;
14988 }
14989 }
14990
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014991 if(not checkDump(1, "2.6")
14992 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014993 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014994 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014995 and $TN2=~/\brestrict\b/) {
14996 return 0;
14997 }
14998 }
14999
15000 if(not checkDump(1, "2.20")
15001 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015002 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015003 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15004 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015005 return 0;
15006 }
15007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015008 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015009 else
15010 {
15011 # typedef struct {...} type_t
15012 # typedef struct type_t {...} type_t
15013 if(index($TN1, " ".$TN2)!=-1)
15014 {
15015 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15016 return 0;
15017 }
15018 }
15019 if(index($TN2, " ".$TN1)!=-1)
15020 {
15021 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15022 return 0;
15023 }
15024 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015025
15026 if($TT1 eq "FuncPtr"
15027 and $TT2 eq "FuncPtr")
15028 {
15029 my $TN1_C = $TN1;
15030 my $TN2_C = $TN2;
15031
15032 $TN1_C=~s/\b(struct|union) //g;
15033 $TN2_C=~s/\b(struct|union) //g;
15034
15035 if($TN1_C eq $TN2_C) {
15036 return 0;
15037 }
15038 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015039 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015040
15041 my ($N1, $N2) = ($TN1, $TN2);
15042 $N1=~s/\b(struct|union) //g;
15043 $N2=~s/\b(struct|union) //g;
15044
15045 if($N1 eq $N2)
15046 { # QList<struct QUrl> and QList<QUrl>
15047 return 0;
15048 }
15049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015050 return 1;
15051}
15052
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015053sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015054{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015055 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015056 if(defined $Cache{"differentDumps"}{$Check}) {
15057 return $Cache{"differentDumps"}{$Check};
15058 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015059 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015060 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015061 if($Check eq "G")
15062 {
15063 if(getGccVersion(1) ne getGccVersion(2))
15064 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015065 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015066 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015067 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015068 if($Check eq "V")
15069 {
15070 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15071 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15072 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015073 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015076 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015077 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015078}
15079
15080sub formatVersion($$)
15081{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015082 my ($V, $Digits) = @_;
15083 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015084 return join(".", splice(@Elems, 0, $Digits));
15085}
15086
15087sub htmlSpecChars($)
15088{
15089 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015090 if(not $Str) {
15091 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015093 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15094 $Str=~s/</&lt;/g;
15095 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15096 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015097 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15098 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015099 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015100 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 $Str=~s/\n/<br\/>/g;
15102 $Str=~s/\"/&quot;/g;
15103 $Str=~s/\'/&#39;/g;
15104 return $Str;
15105}
15106
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015107sub xmlSpecChars($)
15108{
15109 my $Str = $_[0];
15110 if(not $Str) {
15111 return $Str;
15112 }
15113
15114 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15115 $Str=~s/</&lt;/g;
15116 $Str=~s/>/&gt;/g;
15117
15118 $Str=~s/\"/&quot;/g;
15119 $Str=~s/\'/&#39;/g;
15120
15121 return $Str;
15122}
15123
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015124sub xmlSpecChars_R($)
15125{
15126 my $Str = $_[0];
15127 if(not $Str) {
15128 return $Str;
15129 }
15130
15131 $Str=~s/&amp;/&/g;
15132 $Str=~s/&lt;/</g;
15133 $Str=~s/&gt;/>/g;
15134
15135 $Str=~s/&quot;/"/g;
15136 $Str=~s/&#39;/'/g;
15137
15138 return $Str;
15139}
15140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015141sub black_name($)
15142{
15143 my $Name = $_[0];
15144 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15145}
15146
15147sub highLight_Signature($)
15148{
15149 my $Signature = $_[0];
15150 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15151}
15152
15153sub highLight_Signature_Italic_Color($)
15154{
15155 my $Signature = $_[0];
15156 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15157}
15158
15159sub separate_symbol($)
15160{
15161 my $Symbol = $_[0];
15162 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15163 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15164 ($Name, $Spec, $Ver) = ($1, $2, $3);
15165 }
15166 return ($Name, $Spec, $Ver);
15167}
15168
15169sub cut_f_attrs($)
15170{
15171 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15172 return $2;
15173 }
15174 return "";
15175}
15176
15177sub highLight_Signature_PPos_Italic($$$$$)
15178{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015179 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15180 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015181 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15182 my $Return = "";
15183 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15184 $Return = $2;
15185 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015186 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015187 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015188 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015190 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015191 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015192 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015193 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015194 }
15195 return $Signature;
15196 }
15197 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15198 $Begin.=" " if($Begin!~/ \Z/);
15199 $End = cut_f_attrs($Signature);
15200 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015201 my ($Short, $Params) = split_Signature($Signature);
15202 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015203 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015204 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015205 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015206 $Part=~s/\A\s+|\s+\Z//g;
15207 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15208 if($Part=~/\([\*]+(\w+)\)/i) {
15209 $ParamName = $1;#func-ptr
15210 }
15211 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15212 $ParamName = $1;
15213 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015214 if(not $ParamName)
15215 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 push(@Parts, $Part_Styled);
15217 next;
15218 }
15219 if($ItalicParams and not $TName_Tid{1}{$Part}
15220 and not $TName_Tid{2}{$Part})
15221 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015222 my $Style = "<i>$ParamName</i>";
15223
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015224 if($Param_Pos ne ""
15225 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015226 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227 }
15228 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015229 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015230 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015231
15232 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015233 }
15234 $Part_Styled=~s/,(\w)/, $1/g;
15235 push(@Parts, $Part_Styled);
15236 }
15237 if(@Parts)
15238 {
15239 foreach my $Num (0 .. $#Parts)
15240 {
15241 if($Num==$#Parts)
15242 { # add ")" to the last parameter
15243 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15244 }
15245 elsif(length($Parts[$Num])<=45) {
15246 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15247 }
15248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015249 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015250 }
15251 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015252 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253 }
15254 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015255 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015257 $Signature=~s!\[\]![&#160;]!g;
15258 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015259 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15260 if($SymbolVersion) {
15261 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15262 }
15263 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015264}
15265
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015266sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015267{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015268 my $Signature = $_[0];
15269 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15270 {
15271 $Signature=~s/\A\Q$ShortName\E\(//g;
15272 cut_f_attrs($Signature);
15273 $Signature=~s/\)\Z//;
15274 return ($ShortName, $Signature);
15275 }
15276
15277 # error
15278 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015279}
15280
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015281sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015282{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015283 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015285 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15286 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287 foreach my $Pos (0 .. length($Params) - 1)
15288 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015289 my $S = substr($Params, $Pos, 1);
15290 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015291 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 }
15293 if($S eq "," and
15294 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015295 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015296 if($Comma)
15297 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015298 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015299 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015300 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301 }
15302 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015303 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015304 }
15305 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015306 if(not $Sp)
15307 { # remove spaces
15308 foreach (@Parts)
15309 {
15310 s/\A //g;
15311 s/ \Z//g;
15312 }
15313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015314 return @Parts;
15315}
15316
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015317sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015318{
15319 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015320 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015321 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015322 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15323 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015324 $Center+=length($1);
15325 }
15326 foreach my $Pos (0 .. length($Sign)-1)
15327 {
15328 my $S = substr($Sign, $Pos, 1);
15329 if($S eq $Target)
15330 {
15331 if($B{"("}==$B{")"}
15332 and $B{"<"}==$B{">"}) {
15333 return $Center;
15334 }
15335 }
15336 if(defined $B{$S}) {
15337 $B{$S}+=1;
15338 }
15339 $Center+=1;
15340 }
15341 return 0;
15342}
15343
15344sub appendFile($$)
15345{
15346 my ($Path, $Content) = @_;
15347 return if(not $Path);
15348 if(my $Dir = get_dirname($Path)) {
15349 mkpath($Dir);
15350 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015351 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015352 print FILE $Content;
15353 close(FILE);
15354}
15355
15356sub writeFile($$)
15357{
15358 my ($Path, $Content) = @_;
15359 return if(not $Path);
15360 if(my $Dir = get_dirname($Path)) {
15361 mkpath($Dir);
15362 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015363 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015364 print FILE $Content;
15365 close(FILE);
15366}
15367
15368sub readFile($)
15369{
15370 my $Path = $_[0];
15371 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015372 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015373 local $/ = undef;
15374 my $Content = <FILE>;
15375 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015376 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015377 $Content=~s/\r/\n/g;
15378 }
15379 return $Content;
15380}
15381
15382sub get_filename($)
15383{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015384 if(defined $Cache{"get_filename"}{$_[0]}) {
15385 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015386 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015387 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15388 return ($Cache{"get_filename"}{$_[0]}=$1);
15389 }
15390 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391}
15392
15393sub get_dirname($)
15394{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015395 if(defined $Cache{"get_dirname"}{$_[0]}) {
15396 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015397 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015398 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15399 return ($Cache{"get_dirname"}{$_[0]}=$1);
15400 }
15401 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015402}
15403
15404sub separate_path($) {
15405 return (get_dirname($_[0]), get_filename($_[0]));
15406}
15407
15408sub esc($)
15409{
15410 my $Str = $_[0];
15411 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15412 return $Str;
15413}
15414
15415sub readLineNum($$)
15416{
15417 my ($Path, $Num) = @_;
15418 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015419 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015420 foreach (1 ... $Num) {
15421 <FILE>;
15422 }
15423 my $Line = <FILE>;
15424 close(FILE);
15425 return $Line;
15426}
15427
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015428sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015429{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015430 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015431 return () if(not $Path or not -f $Path);
15432 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015433 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15434 {
15435 foreach my $AttrVal (split(/;/, $1))
15436 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437 if($AttrVal=~/(.+):(.+)/)
15438 {
15439 my ($Name, $Value) = ($1, $2);
15440 $Attributes{$Name} = $Value;
15441 }
15442 }
15443 }
15444 return \%Attributes;
15445}
15446
15447sub is_abs($) {
15448 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15449}
15450
15451sub get_abs_path($)
15452{ # abs_path() should NOT be called for absolute inputs
15453 # because it can change them
15454 my $Path = $_[0];
15455 if(not is_abs($Path)) {
15456 $Path = abs_path($Path);
15457 }
15458 return $Path;
15459}
15460
15461sub get_OSgroup()
15462{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015463 my $N = $Config{"osname"};
15464 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015465 return "macos";
15466 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015467 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015468 return "bsd";
15469 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015470 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015471 return "beos";
15472 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015473 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015474 return "symbian";
15475 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015476 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477 return "windows";
15478 }
15479 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015480 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481 }
15482}
15483
15484sub getGccVersion($)
15485{
15486 my $LibVersion = $_[0];
15487 if($GCC_VERSION{$LibVersion})
15488 { # dump version
15489 return $GCC_VERSION{$LibVersion};
15490 }
15491 elsif($UsedDump{$LibVersion}{"V"})
15492 { # old-version dumps
15493 return "unknown";
15494 }
15495 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15496 if(not $GccVersion) {
15497 return "unknown";
15498 }
15499 return $GccVersion;
15500}
15501
15502sub showArch($)
15503{
15504 my $Arch = $_[0];
15505 if($Arch eq "arm"
15506 or $Arch eq "mips") {
15507 return uc($Arch);
15508 }
15509 return $Arch;
15510}
15511
15512sub getArch($)
15513{
15514 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015515
15516 if($TargetArch) {
15517 return $TargetArch;
15518 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015519 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015520 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015521 return $CPU_ARCH{$LibVersion};
15522 }
15523 elsif($UsedDump{$LibVersion}{"V"})
15524 { # old-version dumps
15525 return "unknown";
15526 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015527
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015528 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529}
15530
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015531sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015532{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015533 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015535 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015536 if(getArch(1) ne getArch(2)
15537 or getArch(1) eq "unknown"
15538 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 { # don't show architecture in the header
15540 $ArchInfo="";
15541 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015542 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015543 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015544 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015545 }
15546 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015547 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015548 }
15549 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015550 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015551 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015552
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015553 my $V1 = $Descriptor{1}{"Version"};
15554 my $V2 = $Descriptor{2}{"Version"};
15555
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015556 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15557 {
15558 my $M1 = $UsedDump{1}{"M"};
15559 my $M2 = $UsedDump{2}{"M"};
15560
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015561 my $M1S = $M1;
15562 my $M2S = $M2;
15563
15564 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15565 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15566
15567 if($M1S eq $M2S
15568 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015569 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015570 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15571 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015572 }
15573 else
15574 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015575 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15576 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015577 }
15578 }
15579 else
15580 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015581 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015582 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015583 }
15584
15585 $Title .= $ArchInfo;
15586
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015587 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015588 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015589 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015590 $Title = "<h1>".$Title."</h1>\n";
15591 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015592}
15593
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015594sub get_CheckedHeaders($)
15595{
15596 my $LibVersion = $_[0];
15597
15598 my @Headers = ();
15599
15600 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15601 {
15602 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015603
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015604 if(not is_target_header($File, $LibVersion)) {
15605 next;
15606 }
15607
15608 if(skipHeader($File, $LibVersion)) {
15609 next;
15610 }
15611
15612 push(@Headers, $Path);
15613 }
15614
15615 return @Headers;
15616}
15617
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015618sub get_SourceInfo()
15619{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015620 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015621
15622 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015623 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015624 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2><hr/>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015625 $CheckedHeaders .= "<div class='h_list'>\n";
15626 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 +040015627 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015628 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15629 my $Name = get_filename($Identity);
15630 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15631 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015632 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015633 $CheckedHeaders .= "</div>\n";
15634 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015635 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015636
15637 if(my @Sources = keys(%{$Registered_Sources{1}}))
15638 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015639 $CheckedSources = "<a name='Sources'></a><h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2><hr/>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015640 $CheckedSources .= "<div class='h_list'>\n";
15641 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15642 {
15643 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15644 my $Name = get_filename($Identity);
15645 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15646 $CheckedSources .= $Name.$Comment."<br/>\n";
15647 }
15648 $CheckedSources .= "</div>\n";
15649 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15650 }
15651
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015652 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015653 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015654 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015655 $CheckedLibs .= "<div class='lib_list'>\n";
15656 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15657 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015658 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015659 $CheckedLibs .= $Library."<br/>\n";
15660 }
15661 $CheckedLibs .= "</div>\n";
15662 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015663 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015664
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015665 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15666}
15667
15668sub get_ObjTitle()
15669{
15670 if(defined $UsedDump{1}{"DWARF"}) {
15671 return "Objects";
15672 }
15673 else {
15674 return ucfirst($SLIB_TYPE)." Libraries";
15675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015676}
15677
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015678sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015679{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015680 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015682
15683 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 {
15685 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015686 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015687 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015688 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015689 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015690 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015691 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015692
15693 if($Severity ne $TargetSeverity) {
15694 next;
15695 }
15696
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015697 if($Kinds_Target{$Kind}{$Target}) {
15698 next;
15699 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015700
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015701 $Kinds_Target{$Kind}{$Target} = 1;
15702 $Type_Problems_Count += 1;
15703 }
15704 }
15705 }
15706 return $Type_Problems_Count;
15707}
15708
15709sub get_Summary($)
15710{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015711 my $Level = $_[0];
15712 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015713 $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 +040015714 %{$RESULT{$Level}} = (
15715 "Problems"=>0,
15716 "Warnings"=>0,
15717 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015718 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015719 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015720 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722 {
15723 if(not defined $CompatRules{$Level}{$Kind})
15724 { # unknown rule
15725 if(not $UnknownRules{$Level}{$Kind})
15726 { # only one warning
15727 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15728 $UnknownRules{$Level}{$Kind}=1;
15729 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015730 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015731 }
15732 }
15733 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015734 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15735 {
15736 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15737 {
15738 if(not defined $CompatRules{$Level}{$Kind})
15739 { # unknown rule
15740 if(not $UnknownRules{$Level}{$Kind})
15741 { # only one warning
15742 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15743 $UnknownRules{$Level}{$Kind}=1;
15744 }
15745 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15746 }
15747 }
15748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015749 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015750 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015751 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 {
15753 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15754 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015755 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015757 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015758 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 $Added += 1;
15760 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015761 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015762 {
15763 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015764 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015765 }
15766 else
15767 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015768 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015769 $I_Other += 1;
15770 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015771 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772 $I_Problems_High += 1;
15773 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015774 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015775 $I_Problems_Medium += 1;
15776 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015777 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015778 $I_Problems_Low += 1;
15779 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015780 if(($Severity ne "Low" or $StrictCompat)
15781 and $Severity ne "Safe") {
15782 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015783 }
15784 }
15785 }
15786 }
15787 }
15788 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015789
15790 my %MethodTypeIndex = ();
15791
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015792 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015793 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015794 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15795 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796 {
15797 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15798 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015799 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15800 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015801 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015802 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15803 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015804
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015805 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15806 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015807 next;
15808 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015809 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15810 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15811
15812 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015813
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015814 if(($Severity ne "Low" or $StrictCompat)
15815 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015816 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015817 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015818 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015819 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015820 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015821 }
15822 }
15823 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015824 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 }
15828 }
15829 }
15830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015831
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015832 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15833 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15834 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15835 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015836
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015837 # changed and removed public symbols
15838 my $SCount = keys(%{$CheckedSymbols{$Level}});
15839 if($ExtendedCheck)
15840 { # don't count external_func_0 for constants
15841 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015842 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015843 if($SCount)
15844 {
15845 my %Weight = (
15846 "High" => 100,
15847 "Medium" => 50,
15848 "Low" => 25
15849 );
15850 foreach (keys(%{$TotalAffected{$Level}})) {
15851 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015852 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015853 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015854 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015855 else {
15856 $RESULT{$Level}{"Affected"} = 0;
15857 }
15858
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015859 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15860 if($RESULT{$Level}{"Affected"}>=100) {
15861 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 }
15863
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015864 $RESULT{$Level}{"Problems"} += $Removed;
15865 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015866 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015867 if($StrictCompat) {
15868 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15869 }
15870 else {
15871 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015873
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015874 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015875 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015876 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015877 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015878 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015879 if($Severity eq "Safe")
15880 {
15881 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015882 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015883 elsif($Severity eq "Low")
15884 {
15885 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015886 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015887 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015888 }
15889
15890 if($C_Problems_Low)
15891 {
15892 if($StrictCompat) {
15893 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15894 }
15895 else {
15896 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015897 }
15898 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015899 if($RESULT{$Level}{"Problems"}
15900 and $RESULT{$Level}{"Affected"}) {
15901 $RESULT{$Level}{"Verdict"} = "incompatible";
15902 }
15903 else {
15904 $RESULT{$Level}{"Verdict"} = "compatible";
15905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015906
15907 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15908 if(not $TotalTypes)
15909 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015910 $TotalTypes = keys(%{$TName_Tid{1}});
15911 }
15912
15913 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15914 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15915
15916 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15917
15918 if($ReportFormat eq "xml")
15919 { # XML
15920 # test info
15921 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15922 $TestInfo .= " <version1>\n";
15923 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015924 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015925 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15926 $TestInfo .= " </version1>\n";
15927
15928 $TestInfo .= " <version2>\n";
15929 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015930 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015931 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15932 $TestInfo .= " </version2>\n";
15933 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15934
15935 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015936 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015937 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015938 $TestResults .= " <headers>\n";
15939 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15940 {
15941 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15942 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15943 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15944 }
15945 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015946 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015947
15948 if(my @Sources = keys(%{$Registered_Sources{1}}))
15949 {
15950 $TestResults .= " <sources>\n";
15951 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15952 {
15953 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15954 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15955 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15956 }
15957 $TestResults .= " </sources>\n";
15958 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015959
15960 $TestResults .= " <libs>\n";
15961 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15962 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015963 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015964 $TestResults .= " <name>$Library</name>\n";
15965 }
15966 $TestResults .= " </libs>\n";
15967
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015968 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015969 $TestResults .= " <types>".$TotalTypes."</types>\n";
15970
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015971 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15972 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15974
15975 # problem summary
15976 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15977 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15978
15979 $Problem_Summary .= " <problems_with_types>\n";
15980 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15981 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15982 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15983 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15984 $Problem_Summary .= " </problems_with_types>\n";
15985
15986 $Problem_Summary .= " <problems_with_symbols>\n";
15987 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15988 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15989 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015990 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015991 $Problem_Summary .= " </problems_with_symbols>\n";
15992
15993 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015994 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015995 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015997 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15998
15999 return ($TestInfo.$TestResults.$Problem_Summary, "");
16000 }
16001 else
16002 { # HTML
16003 # test info
16004 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016005 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016006
16007 if($TargetComponent eq "library") {
16008 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16009 }
16010 else {
16011 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016013
16014 my (@VInf1, @VInf2, $AddTestInfo) = ();
16015 if($Arch1 ne "unknown"
16016 and $Arch2 ne "unknown")
16017 { # CPU arch
16018 if($Arch1 eq $Arch2)
16019 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016020 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016021 }
16022 else
16023 { # go to the version number
16024 push(@VInf1, showArch($Arch1));
16025 push(@VInf2, showArch($Arch2));
16026 }
16027 }
16028 if($GccV1 ne "unknown"
16029 and $GccV2 ne "unknown"
16030 and $OStarget ne "windows")
16031 { # GCC version
16032 if($GccV1 eq $GccV2)
16033 { # go to the separate section
16034 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16035 }
16036 else
16037 { # go to the version number
16038 push(@VInf1, "gcc ".$GccV1);
16039 push(@VInf2, "gcc ".$GccV2);
16040 }
16041 }
16042 # show long version names with GCC version and CPU architecture name (if different)
16043 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16044 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16045 $TestInfo .= $AddTestInfo;
16046 #if($COMMON_LANGUAGE{1}) {
16047 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16048 #}
16049 if($ExtendedCheck) {
16050 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016052 if($JoinReport)
16053 {
16054 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016055 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016056 }
16057 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016058 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016059 }
16060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016061 $TestInfo .= "</table>\n";
16062
16063 # test results
16064 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016065 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016066
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016067 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016068 {
16069 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16070 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16071 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016072
16073 if(my @Sources = keys(%{$Registered_Sources{1}}))
16074 {
16075 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16076 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016078
16079 if(not $ExtendedCheck)
16080 {
16081 my $Libs_Link = "0";
16082 $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 +040016083 $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 +040016084 }
16085
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016086 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016087
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016088 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016089 if($JoinReport) {
16090 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16091 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016092
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016093 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016094
16095 $TestResults .= "<tr><th>Compatibility</th>\n";
16096 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16097 {
16098 my $Cl = "incompatible";
16099 if($BC_Rate>=90) {
16100 $Cl = "warning";
16101 }
16102 elsif($BC_Rate>=80) {
16103 $Cl = "almost_compatible";
16104 }
16105
16106 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016107 }
16108 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016109 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016110 }
16111 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016112 $TestResults .= "</table>\n";
16113
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016114 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016115 # problem summary
16116 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016117 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016118 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16119
16120 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016121 if($Added>0)
16122 {
16123 if($JoinReport) {
16124 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16125 }
16126 else {
16127 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16128 }
16129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016130 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016131 $Problem_Summary .= "<tr><th>Added Symbols</th><td>-</td><td".getStyle("I", "Added", $Added).">$Added_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132
16133 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016134 if($Removed>0)
16135 {
16136 if($JoinReport) {
16137 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16138 }
16139 else {
16140 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16141 }
16142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016143 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016144 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016145 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146
16147 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 $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 +040016149 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016150 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016151 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152
16153 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016154 $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 +040016155 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016156 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("T", "Medium", $T_Problems_Medium).">$TM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016157
16158 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016159 $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 +040016160 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016161 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("T", "Low", $T_Problems_Low).">$TL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016162
16163 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016164 $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 +040016165 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016166 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016167 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016168
16169 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016170 $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 +040016171 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016172 $Problem_Summary .= "<tr><td>Medium</td><td".getStyle("I", "Medium", $I_Problems_Medium).">$IM_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016173
16174 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016175 $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 +040016176 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016177 $Problem_Summary .= "<tr><td>Low</td><td".getStyle("I", "Low", $I_Problems_Low).">$IL_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016178
16179 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016180 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16181 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016183 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016184 $Problem_Summary .= "<tr><th>Problems with<br/>Constants</th><td>Low</td><td".getStyle("C", "Low", $C_Problems_Low).">$ChangedConstants_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016186 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016187 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 {
16189 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016190 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "Safe", $T_Other).">$TS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016191 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016193
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016194 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016195 {
16196 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016197 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "Safe", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016198 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016200
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016201 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016202 {
16203 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016204 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "Safe", $C_Other).">$CS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016205 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016206 }
16207
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016208 $META_DATA .= "tool_version:$TOOL_VERSION";
16209 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016211 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16212 }
16213}
16214
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016215sub getStyle($$$)
16216{
16217 my ($Subj, $Act, $Num) = @_;
16218 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016219 "Added"=>"new",
16220 "Removed"=>"failed",
16221 "Safe"=>"passed",
16222 "Low"=>"warning",
16223 "Medium"=>"failed",
16224 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016225 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016226
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016227 if($Num>0) {
16228 return " class='".$Style{$Act}."'";
16229 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016230
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016231 return "";
16232}
16233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016234sub show_number($)
16235{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016236 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016237 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016238 my $Num = cut_off_number($_[0], 2, 0);
16239 if($Num eq "0")
16240 {
16241 foreach my $P (3 .. 7)
16242 {
16243 $Num = cut_off_number($_[0], $P, 1);
16244 if($Num ne "0") {
16245 last;
16246 }
16247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 }
16249 if($Num eq "0") {
16250 $Num = $_[0];
16251 }
16252 return $Num;
16253 }
16254 return $_[0];
16255}
16256
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016257sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016259 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 if($num!~/\./)
16261 {
16262 $num .= ".";
16263 foreach (1 .. $digs_to_cut-1) {
16264 $num .= "0";
16265 }
16266 }
16267 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16268 {
16269 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16270 $num .= "0";
16271 }
16272 }
16273 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16274 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16275 }
16276 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016277 if($z) {
16278 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 return $num;
16281}
16282
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016283sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016285 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016286 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016287
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016288 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016289 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16290 {
16291 my $Header = $Constants{1}{$Constant}{"Header"};
16292 if(not $Header)
16293 { # added
16294 $Header = $Constants{2}{$Constant}{"Header"}
16295 }
16296
16297 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16298 {
16299 if(not defined $CompatRules{$Level}{$Kind}) {
16300 next;
16301 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016302 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016303 next;
16304 }
16305 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016307 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016309 if($ReportFormat eq "xml")
16310 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016311 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 {
16313 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016314 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016315 {
16316 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016317 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16318 {
16319 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16320 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16321 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016322
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016323 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16324 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16325 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016326 if($Overcome) {
16327 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16328 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016329 $CHANGED_CONSTANTS .= " </problem>\n";
16330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016331 $CHANGED_CONSTANTS .= " </constant>\n";
16332 }
16333 $CHANGED_CONSTANTS .= " </header>\n";
16334 }
16335 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16336 }
16337 else
16338 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016339 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016340 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016341 {
16342 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016343 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016344 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016345 my $Report = "";
16346
16347 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16348 {
16349 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16350 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016351 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016352 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016353 }
16354 if($Report)
16355 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016356 $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 Ponomarenko9e05bee2016-04-03 15:57:20 +030016357 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016358 $Report = insertIDs($Report);
16359 }
16360 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 }
16362 $CHANGED_CONSTANTS .= "<br/>\n";
16363 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016364 if($CHANGED_CONSTANTS)
16365 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016366 my $Title = "Problems with Constants, $TargetSeverity Severity";
16367 if($TargetSeverity eq "Safe")
16368 { # Safe Changes
16369 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016370 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016371 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a><h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016372 }
16373 }
16374 return $CHANGED_CONSTANTS;
16375}
16376
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016377sub getTitle($$$)
16378{
16379 my ($Header, $Library, $NameSpace) = @_;
16380 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016381
16382 # if($Library and $Library!~/\.\w+\Z/) {
16383 # $Library .= " (.$LIB_EXT)";
16384 # }
16385
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016386 if($Header and $Library)
16387 {
16388 $Title .= "<span class='h_name'>$Header</span>";
16389 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16390 }
16391 elsif($Library) {
16392 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16393 }
16394 elsif($Header) {
16395 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16396 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016397
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016398 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016399 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016400 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016401
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016402 return $Title;
16403}
16404
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016405sub get_Report_Added($)
16406{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016407 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016408 my $ADDED_INTERFACES = "";
16409 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016410 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016411 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016412 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016413 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 {
16416 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16417 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016418 if($Level eq "Source" and $ReportFormat eq "html")
16419 { # do not show library name in HTML report
16420 $DyLib = "";
16421 }
16422 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 }
16424 }
16425 }
16426 if($ReportFormat eq "xml")
16427 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016428 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016429 {
16430 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016431 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016432 {
16433 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16436 }
16437 $ADDED_INTERFACES .= " </library>\n";
16438 }
16439 $ADDED_INTERFACES .= " </header>\n";
16440 }
16441 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16442 }
16443 else
16444 { # HTML
16445 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016446 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016448 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016450 my %NameSpaceSymbols = ();
16451 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016452 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016453 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016456 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16457 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 foreach my $Interface (@SortedInterfaces)
16459 {
16460 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 my $Signature = get_Signature($Interface, 2);
16462 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016463 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016464 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016465 if($Interface=~/\A(_Z|\?)/)
16466 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016468 $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 +040016469 }
16470 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016471 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 }
16473 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016474 else
16475 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016477 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 }
16479 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 }
16482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016483 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016486 }
16487 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016488 if($ADDED_INTERFACES)
16489 {
16490 my $Anchor = "<a name='Added'></a>";
16491 if($JoinReport) {
16492 $Anchor = "<a name='".$Level."_Added'></a>";
16493 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016494 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 }
16496 }
16497 return $ADDED_INTERFACES;
16498}
16499
16500sub get_Report_Removed($)
16501{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016502 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016503 my $REMOVED_INTERFACES = "";
16504 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016505 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016507 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016508 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016509 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016510 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016511 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16512 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016513 if($Level eq "Source" and $ReportFormat eq "html")
16514 { # do not show library name in HTML report
16515 $DyLib = "";
16516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016517 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 }
16519 }
16520 }
16521 if($ReportFormat eq "xml")
16522 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016523 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016524 {
16525 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016527 {
16528 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016529 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16530 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016531 }
16532 $REMOVED_INTERFACES .= " </library>\n";
16533 }
16534 $REMOVED_INTERFACES .= " </header>\n";
16535 }
16536 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16537 }
16538 else
16539 { # HTML
16540 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016543 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016544 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 my %NameSpaceSymbols = ();
16546 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016547 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016550 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016551 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16552 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016553 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 {
16555 $Removed_Number += 1;
16556 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016557 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016559 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016561 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016562 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016564 $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 +040016565 }
16566 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016567 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 }
16569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016570 else
16571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 }
16575 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016576 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 }
16578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 }
16580 }
16581 $REMOVED_INTERFACES .= "<br/>\n";
16582 }
16583 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016584 if($REMOVED_INTERFACES)
16585 {
16586 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16587 if($JoinReport) {
16588 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16589 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016590 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 }
16592 }
16593 return $REMOVED_INTERFACES;
16594}
16595
16596sub getXmlParams($$)
16597{
16598 my ($Content, $Problem) = @_;
16599 return "" if(not $Content or not $Problem);
16600 my %XMLparams = ();
16601 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16602 {
16603 my $Macro = "\@".lc($Attr);
16604 if($Content=~/\Q$Macro\E/) {
16605 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16606 }
16607 }
16608 my @PString = ();
16609 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016610 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 }
16612 if(@PString) {
16613 return " ".join(" ", @PString);
16614 }
16615 else {
16616 return "";
16617 }
16618}
16619
16620sub addMarkup($)
16621{
16622 my $Content = $_[0];
16623 # auto-markup
16624 $Content=~s/\n[ ]*//; # spaces
16625 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16626 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016627 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16629 if($Content=~/\ANOTE:/)
16630 { # notes
16631 $Content=~s!(NOTE):!<b>$1</b>:!g;
16632 }
16633 else {
16634 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16635 }
16636 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16637 my @Keywords = (
16638 "void",
16639 "const",
16640 "static",
16641 "restrict",
16642 "volatile",
16643 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016644 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 );
16646 my $MKeys = join("|", @Keywords);
16647 foreach (@Keywords) {
16648 $MKeys .= "|non-".$_;
16649 }
16650 $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 +040016651
16652 # Markdown
16653 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16654 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016655 return $Content;
16656}
16657
16658sub applyMacroses($$$$)
16659{
16660 my ($Level, $Kind, $Content, $Problem) = @_;
16661 return "" if(not $Content or not $Problem);
16662 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16663 $Content = addMarkup($Content);
16664 # macros
16665 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16666 {
16667 my $Macro = "\@".lc($Attr);
16668 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016669 if(not defined $Value
16670 or $Value eq "") {
16671 next;
16672 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016673
16674 if(index($Content, $Macro)==-1) {
16675 next;
16676 }
16677
16678 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16679 and $Kind!~/_Type_/
16680 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016681 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016682 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016683 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016684 $Value = black_name($Value);
16685 }
16686 elsif($Value=~/\s/) {
16687 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16688 }
16689 elsif($Value=~/\A\d+\Z/
16690 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16691 { # bits to bytes
16692 if($Value % $BYTE_SIZE)
16693 { # bits
16694 if($Value==1) {
16695 $Value = "<b>".$Value."</b> bit";
16696 }
16697 else {
16698 $Value = "<b>".$Value."</b> bits";
16699 }
16700 }
16701 else
16702 { # bytes
16703 $Value /= $BYTE_SIZE;
16704 if($Value==1) {
16705 $Value = "<b>".$Value."</b> byte";
16706 }
16707 else {
16708 $Value = "<b>".$Value."</b> bytes";
16709 }
16710 }
16711 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016712 else
16713 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016714 $Value = "<b>".htmlSpecChars($Value)."</b>";
16715 }
16716 $Content=~s/\Q$Macro\E/$Value/g;
16717 }
16718
16719 if($Content=~/(\A|[^\@\w])\@\w/)
16720 {
16721 if(not $IncompleteRules{$Level}{$Kind})
16722 { # only one warning
16723 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16724 $IncompleteRules{$Level}{$Kind} = 1;
16725 }
16726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 return $Content;
16728}
16729
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016730sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016731{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016732 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016733 my $INTERFACE_PROBLEMS = "";
16734 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016735
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016736 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16739 if($SV and defined $CompatProblems{$Level}{$SN}) {
16740 next;
16741 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016742 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16743 my $DyLib = $Symbol_Library{1}{$Symbol};
16744 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16745 { # Symbol with Version
16746 $DyLib = $Symbol_Library{1}{$VSym};
16747 }
16748 if(not $DyLib)
16749 { # const global data
16750 $DyLib = "";
16751 }
16752 if($Level eq "Source" and $ReportFormat eq "html")
16753 { # do not show library name in HTML report
16754 $DyLib = "";
16755 }
16756
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016757 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 {
16759 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016760 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016761 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016762 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16763 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016764 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016765 if($Severity eq $TargetSeverity)
16766 {
16767 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16768 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016769 }
16770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016771 }
16772 }
16773 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016775 if($ReportFormat eq "xml")
16776 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016777 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016778 {
16779 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016780 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016781 {
16782 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016783 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16784 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016785 {
16786 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016787 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016788 {
16789 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16790 {
16791 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016792 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016793
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16795 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16796 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16797 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16798 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016799 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16800 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016802 $INTERFACE_PROBLEMS .= " </problem>\n";
16803 }
16804 }
16805 $INTERFACE_PROBLEMS .= " </symbol>\n";
16806 }
16807 $INTERFACE_PROBLEMS .= " </library>\n";
16808 }
16809 $INTERFACE_PROBLEMS .= " </header>\n";
16810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016811 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016812 }
16813 else
16814 { # HTML
16815 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016816 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016818 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016819 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016820 my (%NameSpaceSymbols, %NewSignature) = ();
16821 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016822 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016824 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016825 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016826 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016827 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 +040016828 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016829 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016830 my $Signature = get_Signature($Symbol, 1);
16831 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016832 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016833 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016835 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016836 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016837 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016838 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016839 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016840 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016841 }
16842 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16843 {
16844 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016845 $SYMBOL_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>".$Effect."</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 $ProblemNum += 1;
16847 $ProblemsNum += 1;
16848 }
16849 }
16850 }
16851 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016852 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016853 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016854 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016855 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016856 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016857 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016858
16859 if($NameSpace)
16860 {
16861 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16862 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016863 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016864
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016865 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol." <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>".$ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016866 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016867
16868 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016870 if($NameSpace) {
16871 $NSign = cut_Namespace($NSign, $NameSpace);
16872 }
16873 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span>\n<br/>\n<span class='new_sign'>".highLight_Signature_Italic_Color($NSign)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016875
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016876 if($Symbol=~/\A(_Z|\?)/) {
16877 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16878 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016879
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016880 $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 +040016881 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 }
16883 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016884 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016885 }
16886 }
16887 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016888
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 if($INTERFACE_PROBLEMS)
16890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16892 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16893 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 { # Safe Changes
16895 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016897 $INTERFACE_PROBLEMS = "<a name=\'".get_Anchor("Symbol", $Level, $TargetSeverity)."\'></a><a name=\'".get_Anchor("Interface", $Level, $TargetSeverity)."\'></a>\n<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016898 }
16899 }
16900 return $INTERFACE_PROBLEMS;
16901}
16902
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016903sub cut_Namespace($$)
16904{
16905 my ($N, $Ns) = @_;
16906 $N=~s/\b\Q$Ns\E:://g;
16907 return $N;
16908}
16909
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910sub get_Report_TypeProblems($$)
16911{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016913 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016914
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016915 my %ReportMap = ();
16916 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016917
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016918 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016919 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016920 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
16921
16922 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016923 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016924 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016925 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016926 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016927 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016928
16929 if($Severity eq $TargetSeverity)
16930 {
16931 $ReportMap{$HeaderName}{$TypeName} = 1;
16932 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016935 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016936 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016938 if($ReportFormat eq "xml")
16939 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016940 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 {
16942 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016943 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016944 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016945 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016946 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016947 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016948 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016949 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016951 $Kinds_Locations{$Kind}{$Location} = 1;
16952
16953 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
16954 if($Kinds_Target{$Kind}{$Target}) {
16955 next;
16956 }
16957 $Kinds_Target{$Kind}{$Target} = 1;
16958
16959 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16961 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16962 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16963 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16964 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016965 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16966 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016968 $TYPE_PROBLEMS .= " </problem>\n";
16969 }
16970 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016971 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016972 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016973 $TYPE_PROBLEMS .= showVTables($TypeName);
16974 }
16975 $TYPE_PROBLEMS .= " </type>\n";
16976 }
16977 $TYPE_PROBLEMS .= " </header>\n";
16978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016979 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016980 }
16981 else
16982 { # HTML
16983 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016984 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 my (%NameSpace_Type) = ();
16987 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016988 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016989 }
16990 foreach my $NameSpace (sort keys(%NameSpace_Type))
16991 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016992 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016993 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 +040016994 foreach my $TypeName (@SortedTypes)
16995 {
16996 my $ProblemNum = 1;
16997 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016998 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016999
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017000 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017001 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017002 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017003 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017004 $Kinds_Locations{$Kind}{$Location} = 1;
17005
17006 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17007 if($Kinds_Target{$Kind}{$Target}) {
17008 next;
17009 }
17010 $Kinds_Target{$Kind}{$Target} = 1;
17011
17012 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17014 {
17015 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017016 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 $ProblemNum += 1;
17018 $ProblemsNum += 1;
17019 }
17020 }
17021 }
17022 $ProblemNum -= 1;
17023 if($TYPE_REPORT)
17024 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017025 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017026 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017027 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 $ShowVTables = showVTables($TypeName);
17029 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017030
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017031 my $ShowType = show_Type($TypeName, 1, 1);
17032
17033 if($NameSpace)
17034 {
17035 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17036 $ShowType = cut_Namespace($ShowType, $NameSpace);
17037 $Affected = cut_Namespace($Affected, $NameSpace);
17038 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17039 }
17040
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017041 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType." <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017042 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17043 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17044 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17045 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017046 }
17047 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017048 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017049 }
17050 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017052 if($TYPE_PROBLEMS)
17053 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017054 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17055 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017056 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017057 { # Safe Changes
17058 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017059 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017060 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017061 }
17062 }
17063 return $TYPE_PROBLEMS;
17064}
17065
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017066sub show_Type($$$)
17067{
17068 my ($Name, $Html, $LibVersion) = @_;
17069 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17070 $TType = lc($TType);
17071 if($TType=~/struct|union|enum/) {
17072 $Name=~s/\A\Q$TType\E //g;
17073 }
17074 if($Html) {
17075 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17076 }
17077 else {
17078 $Name = $TType." ".$Name;
17079 }
17080 return $Name;
17081}
17082
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017083sub get_Anchor($$$)
17084{
17085 my ($Kind, $Level, $Severity) = @_;
17086 if($JoinReport)
17087 {
17088 if($Severity eq "Safe") {
17089 return "Other_".$Level."_Changes_In_".$Kind."s";
17090 }
17091 else {
17092 return $Kind."_".$Level."_Problems_".$Severity;
17093 }
17094 }
17095 else
17096 {
17097 if($Severity eq "Safe") {
17098 return "Other_Changes_In_".$Kind."s";
17099 }
17100 else {
17101 return $Kind."_Problems_".$Severity;
17102 }
17103 }
17104}
17105
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106sub showVTables($)
17107{
17108 my $TypeName = $_[0];
17109 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017110 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 if(defined $Type1{"VTable"}
17112 and keys(%{$Type1{"VTable"}}))
17113 {
17114 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017115 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017116 if(defined $Type2{"VTable"}
17117 and keys(%{$Type2{"VTable"}}))
17118 {
17119 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17120 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017121 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017123 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17124 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 }
17126 my $VTABLES = "";
17127 if($ReportFormat eq "xml")
17128 { # XML
17129 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017130 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017132 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017133 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17134 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 $VTABLES .= " </entry>\n";
17136 }
17137 $VTABLES .= " </vtable>\n\n";
17138 }
17139 else
17140 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017141 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017142 $VTABLES .= "<tr><th>Offset</th>";
17143 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017144 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017145 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017146 {
17147 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017148
17149 my $E1 = $Entries{$Index}{"E1"};
17150 my $E2 = $Entries{$Index}{"E2"};
17151
17152 if($E1 ne $E2
17153 and $E1!~/ 0x/
17154 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017155 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017156 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017158 $Color1 = " class='failed'";
17159 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017160 }
17161 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017162 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 }
17164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017165 $VTABLES .= "<tr><th>".$Index."</th>\n";
17166 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17167 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017168 }
17169 $VTABLES .= "</table><br/>\n";
17170 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017171 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017172 }
17173 return $VTABLES;
17174 }
17175 }
17176 return "";
17177}
17178
17179sub simpleVEntry($)
17180{
17181 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017182 if(not defined $VEntry
17183 or $VEntry eq "") {
17184 return "";
17185 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017186
17187 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017188 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17189 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17190 if($VEntry=~/\A_ZThn.+\Z/) {
17191 $VEntry = "non-virtual thunk";
17192 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017193 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017194 # support for old GCC versions
17195 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17196 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17197 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017198 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17199 return $VEntry;
17200}
17201
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017202sub adjustParamPos($$$)
17203{
17204 my ($Pos, $Symbol, $LibVersion) = @_;
17205 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17206 {
17207 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17208 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17209 {
17210 return $Pos-1;
17211 }
17212
17213 return $Pos;
17214 }
17215
17216 return undef;
17217}
17218
17219sub getParamPos($$$)
17220{
17221 my ($Name, $Symbol, $LibVersion) = @_;
17222
17223 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17224 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17225 {
17226 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17227 foreach (keys(%{$Info->{"Param"}}))
17228 {
17229 if($Info->{"Param"}{$_}{"name"} eq $Name)
17230 {
17231 return $_;
17232 }
17233 }
17234 }
17235
17236 return undef;
17237}
17238
17239sub getParamName($)
17240{
17241 my $Loc = $_[0];
17242 $Loc=~s/\->.*//g;
17243 return $Loc;
17244}
17245
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017246sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017247{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017248 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017249
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017250 my $LIMIT = 10;
17251 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017252 $LIMIT = $AffectLimit;
17253 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017254
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017255 my @Kinds = sort keys(%{$Kinds_Locations});
17256 my %KLocs = ();
17257 foreach my $Kind (@Kinds)
17258 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017259 my @Locs = sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$Kinds_Locations->{$Kind}});
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017260 $KLocs{$Kind} = \@Locs;
17261 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017262
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017263 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017264 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017265 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017266 if(index($Symbol, "_Z")==0
17267 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017268 { # duplicated problems for C2 constructors, D2 and D0 destructors
17269 next;
17270 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017271
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017272 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017273 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017274 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017275 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017276 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277 next;
17278 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017279
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017280 if(index($Symbol, "\@")!=-1
17281 or index($Symbol, "\$")!=-1)
17282 {
17283 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17284
17285 if($Level eq "Source")
17286 { # remove symbol version
17287 $Symbol = $SN;
17288 }
17289
17290 if($SV and defined $CompatProblems{$Level}{$SN}
17291 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17292 { # duplicated problems for versioned symbols
17293 next;
17294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017295 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017296
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017297 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017298 if($Type_Name ne $Target_TypeName) {
17299 next;
17300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017302 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017303 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017304 }
17305 }
17306 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017307
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017308 %KLocs = (); # clear
17309
17310 my %SymSel = ();
17311 my $Num = 0;
17312 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017313 {
17314 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17315 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017316 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017317 {
17318 $SymSel{$Symbol}{"Loc"} = $Loc;
17319 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017320 last LOOP;
17321 }
17322 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017323
17324 $Num += 1;
17325
17326 if($Num>=$LIMIT) {
17327 last;
17328 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017329 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017330
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017331 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017333 if($ReportFormat eq "xml")
17334 { # XML
17335 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017336
17337 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017339 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017340 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017341 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017342
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017343 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017344 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017345 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017346 $Target .= " param=\"$PName\"";
17347 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017348 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017349 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017350 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017351 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017352 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017353 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017354 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017355
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017356 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017357 $Target .= " field=\"$1\"";
17358 }
17359
17360 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017361 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362 $Affected .= " </symbol>\n";
17363 }
17364 $Affected .= " </affected>\n";
17365 }
17366 else
17367 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017368 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017370 my $Kind = $SymSel{$Symbol}{"Kind"};
17371 my $Loc = $SymSel{$Symbol}{"Loc"};
17372
17373 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017374 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017375 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017376 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17377
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017378 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017379 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017380 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017381
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017382 if(keys(%SymLocKind)>$LIMIT) {
17383 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017384 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017385
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017386 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017387 if($Affected)
17388 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017389 my $Num = keys(%SymLocKind);
17390 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017391 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017392 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 }
17394 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 return $Affected;
17397}
17398
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017399sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017400{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017401 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017402 if($L2=~/\A(retval|this)\b/
17403 and $L1!~/\A(retval|this)\b/)
17404 {
17405 if($L1!~/\-\>/) {
17406 return 1;
17407 }
17408 elsif($L2=~/\-\>/) {
17409 return 1;
17410 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017411 }
17412 return 0;
17413}
17414
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017415sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017416{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017417 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017418
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017419 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017420
17421 my $Location_I = $Location;
17422 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17423
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017424 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017425
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017426 if($Kind eq "Overridden_Virtual_Method"
17427 or $Kind eq "Overridden_Virtual_Method_B") {
17428 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17429 }
17430 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17431 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017432 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17433
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017434 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17435 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017436 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17437 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017439 if($ClassName eq $Problem{"Type_Name"}) {
17440 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17441 }
17442 else {
17443 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17444 }
17445 }
17446 else
17447 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017448 my $TypeID = undef;
17449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017450 if($Location=~/retval/)
17451 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017452 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017453 push(@Sentence, "Field \'".$Location."\' in return value");
17454 }
17455 else {
17456 push(@Sentence, "Return value");
17457 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017458
17459 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017460 }
17461 elsif($Location=~/this/)
17462 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017463 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017464 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17465 }
17466 else {
17467 push(@Sentence, "\'this\' pointer");
17468 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017469
17470 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017471 }
17472 else
17473 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017474
17475 my $PName = getParamName($Location);
17476 my $PPos = getParamPos($PName, $Symbol, 1);
17477
17478 if(index($Location, "->")!=-1) {
17479 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017480 }
17481 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017482 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017483 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017484 if($PName) {
17485 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017486 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017487
17488 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17489 }
17490
17491 if($Location!~/this/)
17492 {
17493 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017494 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017495 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017496 push(@Sentence, "(pointer)");
17497 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017498 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017499 push(@Sentence, "(reference)");
17500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017501 }
17502 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017503
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 if($Location eq "this") {
17505 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17506 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017507 else
17508 {
17509 my $Location_T = $Location;
17510 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17511
17512 my $TypeID_Problem = $TypeID;
17513 if($Location_T) {
17514 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17515 }
17516
17517 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17518 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17519 }
17520 else {
17521 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017523 }
17524 }
17525 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017526 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017527 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 +040017528 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017529
17530 my $Sent = join(" ", @Sentence);
17531
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017532 $Sent=~s/->/./g;
17533
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017534 if($ReportFormat eq "xml")
17535 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017536 $Sent=~s/'//g;
17537 }
17538
17539 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017540}
17541
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017542sub getFieldType($$$)
17543{
17544 my ($Location, $TypeId, $LibVersion) = @_;
17545
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017546 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017547
17548 foreach my $Name (@Fields)
17549 {
17550 my %Info = get_BaseType($TypeId, $LibVersion);
17551
17552 foreach my $Pos (keys(%{$Info{"Memb"}}))
17553 {
17554 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17555 {
17556 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17557 last;
17558 }
17559 }
17560 }
17561
17562 return $TypeId;
17563}
17564
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017565sub get_XmlSign($$)
17566{
17567 my ($Symbol, $LibVersion) = @_;
17568 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17569 my $Report = "";
17570 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17571 {
17572 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017573 my $Type = $Info->{"Param"}{$Pos}{"type"};
17574 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017575 foreach my $Typedef (keys(%ChangedTypedef))
17576 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017577 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17578 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017580 }
17581 $Report .= " <param pos=\"$Pos\">\n";
17582 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017583 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584 $Report .= " </param>\n";
17585 }
17586 if(my $Return = $Info->{"Return"})
17587 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017588 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017589 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017590 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017591 $Report .= " </retval>\n";
17592 }
17593 return $Report;
17594}
17595
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017596sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017597{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017598 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017599 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017600 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017601 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017602 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17603 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017604 next;
17605 }
17606 $Report .= " <symbol name=\"$Symbol\">\n";
17607 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017608 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017609 {
17610 if(defined $CompleteSignature{1}{$Symbol}
17611 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17612 {
17613 $P1 = get_XmlSign($Symbol, 1);
17614 $S1 = get_Signature($Symbol, 1);
17615 }
17616 elsif($Symbol=~/\A(_Z|\?)/) {
17617 $S1 = $tr_name{$Symbol};
17618 }
17619 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017620 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017621 {
17622 if(defined $CompleteSignature{2}{$Symbol}
17623 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17624 {
17625 $P2 = get_XmlSign($Symbol, 2);
17626 $S2 = get_Signature($Symbol, 2);
17627 }
17628 elsif($Symbol=~/\A(_Z|\?)/) {
17629 $S2 = $tr_name{$Symbol};
17630 }
17631 }
17632 if($S1)
17633 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017634 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017635 $Report .= $P1;
17636 $Report .= " </old>\n";
17637 }
17638 if($S2 and $S2 ne $S1)
17639 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017640 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017641 $Report .= $P2;
17642 $Report .= " </new>\n";
17643 }
17644 $Report .= " </symbol>\n";
17645 }
17646 $Report .= "</symbols_info>\n";
17647 return $Report;
17648}
17649
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017650sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017651{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017652 my ($Level, $Report) = @_;
17653 if($ReportFormat eq "xml") {
17654 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017655 }
17656 if($StdOut)
17657 { # --stdout option
17658 print STDOUT $Report;
17659 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017660 else
17661 {
17662 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017663 mkpath(get_dirname($RPath));
17664
17665 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17666 print REPORT $Report;
17667 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017668 }
17669}
17670
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671sub getReport($)
17672{
17673 my $Level = $_[0];
17674 if($ReportFormat eq "xml")
17675 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017676 if($Level eq "Join")
17677 {
17678 my $Report = "<reports>\n";
17679 $Report .= getReport("Binary");
17680 $Report .= getReport("Source");
17681 $Report .= "</reports>\n";
17682 return $Report;
17683 }
17684 else
17685 {
17686 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17687 my ($Summary, $MetaData) = get_Summary($Level);
17688 $Report .= $Summary."\n";
17689 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17690 $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 +040017691
17692 # additional symbols info (if needed)
17693 # $Report .= get_Report_SymbolsInfo($Level);
17694
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017695 $Report .= "</report>\n";
17696 return $Report;
17697 }
17698 }
17699 else
17700 { # HTML
17701 my $CssStyles = readModule("Styles", "Report.css");
17702 my $JScripts = readModule("Scripts", "Sections.js");
17703 if($Level eq "Join")
17704 {
17705 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17706 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017707 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017708 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17709 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 +040017710 my ($BSummary, $BMetaData) = get_Summary("Binary");
17711 my ($SSummary, $SMetaData) = get_Summary("Source");
17712 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 +030017713 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017714 <br/>
17715 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017716 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17717 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017718 </div>";
17719 $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>";
17720 $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 +030017721 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017722 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017723 return $Report;
17724 }
17725 else
17726 {
17727 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017728 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17729 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17730 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 +040017731 if($Level eq "Binary")
17732 {
17733 if(getArch(1) eq getArch(2)
17734 and getArch(1) ne "unknown") {
17735 $Description .= " on ".showArch(getArch(1));
17736 }
17737 }
17738 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 +030017739 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017740 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17741 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17742 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017743 $Report .= "</div>\n<br/><br/><br/>\n";
17744 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017745 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017746 return $Report;
17747 }
17748 }
17749}
17750
17751sub createReport()
17752{
17753 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017754 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017755 writeReport("Join", getReport("Join"));
17756 }
17757 elsif($DoubleReport)
17758 { # default
17759 writeReport("Binary", getReport("Binary"));
17760 writeReport("Source", getReport("Source"));
17761 }
17762 elsif($BinaryOnly)
17763 { # --binary
17764 writeReport("Binary", getReport("Binary"));
17765 }
17766 elsif($SourceOnly)
17767 { # --source
17768 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017769 }
17770}
17771
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017772sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017773{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017774 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017775
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017776 $Footer .= "<hr/>\n";
17777 $Footer .= "<div class='footer' align='right'>";
17778 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17779 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017780 $Footer .= "<br/>\n";
17781
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017782 return $Footer;
17783}
17784
17785sub get_Report_Problems($$)
17786{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017787 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017788
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017789 my $Report = get_Report_TypeProblems($Severity, $Level);
17790 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017791 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017792 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017793
17794 if($Severity eq "Low" or $Severity eq "Safe") {
17795 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017796 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017798 if($ReportFormat eq "html")
17799 {
17800 if($Report)
17801 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017802 if($JoinReport)
17803 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017804 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017805 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17806 }
17807 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017808 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017809 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017811 else
17812 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017813 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017814 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17815 }
17816 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017817 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017819 }
17820 }
17821 }
17822 return $Report;
17823}
17824
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017825sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017826{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017827 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017828
17829 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17830 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17831 $Head .= "<head>\n";
17832 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17833 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17834 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17835 $Head .= "<title>$Title</title>\n";
17836 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17837 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17838 $Head .= "</head>\n";
17839
17840 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017841}
17842
17843sub insertIDs($)
17844{
17845 my $Text = $_[0];
17846 while($Text=~/CONTENT_ID/)
17847 {
17848 if(int($Content_Counter)%2) {
17849 $ContentID -= 1;
17850 }
17851 $Text=~s/CONTENT_ID/c_$ContentID/;
17852 $ContentID += 1;
17853 $Content_Counter += 1;
17854 }
17855 return $Text;
17856}
17857
17858sub checkPreprocessedUnit($)
17859{
17860 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017861 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017862 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017863 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017864
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017865 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017866 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017867 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017868 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017869 chomp($Line);
17870 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017871 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017872 $CurHeader = path_format($1, $OSgroup);
17873 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017874 $CurClass = "";
17875
17876 if(index($CurHeader, $TMP_DIR)==0) {
17877 next;
17878 }
17879
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017880 if(substr($CurHeaderName, 0, 1) eq "<")
17881 { # <built-in>, <command-line>, etc.
17882 $CurHeaderName = "";
17883 $CurHeader = "";
17884 }
17885
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017886 if($ExtraInfo)
17887 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017888 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017889 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17890 }
17891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017892 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017893 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017894 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017895 if($CurHeaderName)
17896 {
17897 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17898 and not $Registered_Headers{$Version}{$CurHeader})
17899 { # not a target
17900 next;
17901 }
17902 if(not is_target_header($CurHeaderName, 1)
17903 and not is_target_header($CurHeaderName, 2))
17904 { # user-defined header
17905 next;
17906 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017907 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017908 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017909
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017910 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017911 {
17912 my ($Name, $Value) = ($1, $2);
17913 if(not $Constants{$Version}{$Name}{"Access"})
17914 {
17915 $Constants{$Version}{$Name}{"Access"} = "public";
17916 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017917 if($CurHeaderName) {
17918 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17919 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017920 }
17921 }
17922 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17923 $Constants{$Version}{$1}{"Access"} = "private";
17924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017925 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017926 else
17927 {
17928 if(defined $ExtraDump)
17929 {
17930 if($Line=~/(\w+)\s*\(/)
17931 { # functions
17932 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17933 }
17934 #elsif($Line=~/(\w+)\s*;/)
17935 #{ # data
17936 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17937 #}
17938 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17939 $CurClass = $2;
17940 }
17941 }
17942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017943 }
17944 close(PREPROC);
17945 foreach my $Constant (keys(%{$Constants{$Version}}))
17946 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017947 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17948 {
17949 delete($Constants{$Version}{$Constant});
17950 next;
17951 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017952 if(not $ExtraDump and ($Constant=~/_h\Z/i
17953 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017954 { # skip
17955 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017956 }
17957 else {
17958 delete($Constants{$Version}{$Constant}{"Access"});
17959 }
17960 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017961 if($Debug)
17962 {
17963 mkpath($DEBUG_PATH{$Version});
17964 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017966}
17967
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017968sub uncoverConstant($$)
17969{
17970 my ($LibVersion, $Constant) = @_;
17971 return "" if(not $LibVersion or not $Constant);
17972 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17973 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17974 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17975 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017976
17977 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017978 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017979 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17980 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017981 {
17982 push(@RecurConstant, $Constant);
17983 my $Uncovered = uncoverConstant($LibVersion, $Value);
17984 if($Uncovered ne "") {
17985 $Value = $Uncovered;
17986 }
17987 pop(@RecurConstant);
17988 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017989
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017990 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017991 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017992 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17993 }
17994 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17995}
17996
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017997sub simpleConstant($$)
17998{
17999 my ($LibVersion, $Value) = @_;
18000 if($Value=~/\W/)
18001 {
18002 my $Value_Copy = $Value;
18003 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18004 {
18005 my $Word = $1;
18006 if($Value!~/$Word\s*\(/)
18007 {
18008 my $Val = uncoverConstant($LibVersion, $Word);
18009 if($Val ne "")
18010 {
18011 $Value=~s/\b$Word\b/$Val/g;
18012 }
18013 }
18014 }
18015 }
18016 return $Value;
18017}
18018
18019sub computeValue($)
18020{
18021 my $Value = $_[0];
18022
18023 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18024 return $1;
18025 }
18026
18027 if($Value=~/\A[\d\-\+()]+\Z/) {
18028 return eval($Value);
18029 }
18030
18031 return $Value;
18032}
18033
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018034my %IgnoreConstant = map {$_=>1} (
18035 "VERSION",
18036 "VERSIONCODE",
18037 "VERNUM",
18038 "VERS_INFO",
18039 "PATCHLEVEL",
18040 "INSTALLPREFIX",
18041 "VBUILD",
18042 "VPATCH",
18043 "VMINOR",
18044 "BUILD_STRING",
18045 "BUILD_TIME",
18046 "PACKAGE_STRING",
18047 "PRODUCTION",
18048 "CONFIGURE_COMMAND",
18049 "INSTALLDIR",
18050 "BINDIR",
18051 "CONFIG_FILE_PATH",
18052 "DATADIR",
18053 "EXTENSION_DIR",
18054 "INCLUDE_PATH",
18055 "LIBDIR",
18056 "LOCALSTATEDIR",
18057 "SBINDIR",
18058 "SYSCONFDIR",
18059 "RELEASE",
18060 "SOURCE_ID",
18061 "SUBMINOR",
18062 "MINOR",
18063 "MINNOR",
18064 "MINORVERSION",
18065 "MAJOR",
18066 "MAJORVERSION",
18067 "MICRO",
18068 "MICROVERSION",
18069 "BINARY_AGE",
18070 "INTERFACE_AGE",
18071 "CORE_ABI",
18072 "PATCH",
18073 "COPYRIGHT",
18074 "TIMESTAMP",
18075 "REVISION",
18076 "PACKAGE_TAG",
18077 "PACKAGEDATE",
18078 "NUMVERSION",
18079 "Release",
18080 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018081);
18082
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018083sub constantFilter($$$)
18084{
18085 my ($Name, $Value, $Level) = @_;
18086
18087 if($Level eq "Binary")
18088 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018089 if($Name=~/_t\Z/)
18090 { # __malloc_ptr_t
18091 return 1;
18092 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018093 foreach (keys(%IgnoreConstant))
18094 {
18095 if($Name=~/(\A|_)$_(_|\Z)/)
18096 { # version
18097 return 1;
18098 }
18099 if(/\A[A-Z].*[a-z]\Z/)
18100 {
18101 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18102 { # version
18103 return 1;
18104 }
18105 }
18106 }
18107 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18108 { # version
18109 return 1;
18110 }
18111 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18112 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18113 return 1;
18114 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018115
18116 if($Value=~/\A["'].*['"]/i)
18117 { # string
18118 return 0;
18119 }
18120
18121 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18122 { # static int gcry_pth_init
18123 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018124 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018125 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018126 return 1;
18127 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018128 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018129 { # foo(p)
18130 return 1;
18131 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018132 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018133 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018134 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018135 return 1;
18136 }
18137 }
18138
18139 return 0;
18140}
18141
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018142sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018143{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018144 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018145 foreach my $Constant (keys(%{$Constants{1}}))
18146 {
18147 if($SkipConstants{1}{$Constant})
18148 { # skipped by the user
18149 next;
18150 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018151
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018152 if(my $Header = $Constants{1}{$Constant}{"Header"})
18153 {
18154 if(not is_target_header($Header, 1)
18155 and not is_target_header($Header, 2))
18156 { # user-defined header
18157 next;
18158 }
18159 }
18160 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018161 next;
18162 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018163
18164 my $Old_Value = uncoverConstant(1, $Constant);
18165
18166 if(constantFilter($Constant, $Old_Value, $Level))
18167 { # separate binary and source problems
18168 next;
18169 }
18170
18171 if(not defined $Constants{2}{$Constant}{"Value"})
18172 { # removed
18173 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18174 "Target"=>$Constant,
18175 "Old_Value"=>$Old_Value );
18176 next;
18177 }
18178
18179 if($Constants{2}{$Constant}{"Value"} eq "")
18180 { # empty value
18181 # TODO: implement a rule
18182 next;
18183 }
18184
18185 my $New_Value = uncoverConstant(2, $Constant);
18186
18187 my $Old_Value_Pure = $Old_Value;
18188 my $New_Value_Pure = $New_Value;
18189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018190 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18191 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18192 $New_Value_Pure=~s/(\W)\s+/$1/g;
18193 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018194
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018195 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018197 if($New_Value_Pure ne $Old_Value_Pure)
18198 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018199 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18200 { # complex values
18201 next;
18202 }
18203 if(computeValue($Old_Value) eq computeValue($New_Value))
18204 { # expressions
18205 next;
18206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018207 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18208 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18209 next;
18210 }
18211 if($Old_Value eq "0" and $New_Value eq "NULL")
18212 { # 0 => NULL
18213 next;
18214 }
18215 if($Old_Value eq "NULL" and $New_Value eq "0")
18216 { # NULL => 0
18217 next;
18218 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018219 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018220 "Target"=>$Constant,
18221 "Old_Value"=>$Old_Value,
18222 "New_Value"=>$New_Value );
18223 }
18224 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018225
18226 foreach my $Constant (keys(%{$Constants{2}}))
18227 {
18228 if(not defined $Constants{1}{$Constant}{"Value"})
18229 {
18230 if($SkipConstants{2}{$Constant})
18231 { # skipped by the user
18232 next;
18233 }
18234
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018235 if(my $Header = $Constants{2}{$Constant}{"Header"})
18236 {
18237 if(not is_target_header($Header, 1)
18238 and not is_target_header($Header, 2))
18239 { # user-defined header
18240 next;
18241 }
18242 }
18243 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018244 next;
18245 }
18246
18247 my $New_Value = uncoverConstant(2, $Constant);
18248 if(not defined $New_Value or $New_Value eq "") {
18249 next;
18250 }
18251
18252 if(constantFilter($Constant, $New_Value, $Level))
18253 { # separate binary and source problems
18254 next;
18255 }
18256
18257 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18258 "Target"=>$Constant,
18259 "New_Value"=>$New_Value );
18260 }
18261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018262}
18263
18264sub convert_integer($)
18265{
18266 my $Value = $_[0];
18267 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018268 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018269 return hex($Value);
18270 }
18271 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018272 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018273 return oct($Value);
18274 }
18275 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018276 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018277 return oct($Value);
18278 }
18279 else {
18280 return $Value;
18281 }
18282}
18283
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018284sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018285{
18286 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018287 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018288 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018289 {
18290 if($LibVersion==1)
18291 {
18292 printMsg("WARNING", "checking headers only");
18293 $CheckHeadersOnly = 1;
18294 }
18295 else {
18296 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18297 }
18298 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018299
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018300 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018301 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018302 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018303
18304 if($CheckUndefined)
18305 {
18306 my %UndefinedLibs = ();
18307
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018308 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18309
18310 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018311 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018312 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018313 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018314 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018315 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018316 if($Symbol_Library{$LibVersion}{$Symbol}
18317 or $DepSymbol_Library{$LibVersion}{$Symbol})
18318 { # exported by target library
18319 next;
18320 }
18321 if(index($Symbol, '@')!=-1)
18322 { # exported default symbol version (@@)
18323 $Symbol=~s/\@/\@\@/;
18324 if($Symbol_Library{$LibVersion}{$Symbol}
18325 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18326 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018327 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018328 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018329 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18330 $UndefinedLibs{$Path} = 1;
18331 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018332 }
18333 }
18334 }
18335 if($ExtraInfo)
18336 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018337 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018338 {
18339 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018340 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018341 foreach (@Paths)
18342 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018343 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018344 my ($Dir, $Name) = separate_path($_);
18345
18346 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018347 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018348 }
18349
18350 $Name = parse_libname($Name, "name", $OStarget);
18351 $Name=~s/\Alib//;
18352
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018353 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018354 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018355
18356 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18357 {
18358 $LibString = " -L".esc($Dir).$LibString;
18359 }
18360
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018361 writeFile($ExtraInfo."/libs-string", $LibString);
18362 }
18363 }
18364 }
18365
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018366 if($ExtraInfo) {
18367 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18368 }
18369
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018370 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018371 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018372 if($#LibPaths!=-1)
18373 {
18374 if(not keys(%{$Symbol_Library{$LibVersion}}))
18375 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018376 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018377 printMsg("WARNING", "checking headers only");
18378 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018379 }
18380 }
18381 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018382
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018383 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018384 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018385}
18386
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018387my %Prefix_Lib_Map=(
18388 # symbols for autodetecting library dependencies (by prefix)
18389 "pthread_" => ["libpthread"],
18390 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18391 "cairo_" => ["libcairo"],
18392 "gtk_" => ["libgtk-x11-2.0"],
18393 "atk_" => ["libatk-1.0"],
18394 "gdk_" => ["libgdk-x11-2.0"],
18395 "gl" => ["libGL"],
18396 "glu" => ["libGLU"],
18397 "popt" => ["libpopt"],
18398 "Py" => ["libpython"],
18399 "jpeg_" => ["libjpeg"],
18400 "BZ2_" => ["libbz2"],
18401 "Fc" => ["libfontconfig"],
18402 "Xft" => ["libXft"],
18403 "SSL_" => ["libssl"],
18404 "sem_" => ["libpthread"],
18405 "snd_" => ["libasound"],
18406 "art_" => ["libart_lgpl_2"],
18407 "dbus_g" => ["libdbus-glib-1"],
18408 "GOMP_" => ["libgomp"],
18409 "omp_" => ["libgomp"],
18410 "cms" => ["liblcms"]
18411);
18412
18413my %Pattern_Lib_Map=(
18414 "SL[a-z]" => ["libslang"]
18415);
18416
18417my %Symbol_Lib_Map=(
18418 # symbols for autodetecting library dependencies (by name)
18419 "pow" => "libm",
18420 "fmod" => "libm",
18421 "sin" => "libm",
18422 "floor" => "libm",
18423 "cos" => "libm",
18424 "dlopen" => "libdl",
18425 "deflate" => "libz",
18426 "inflate" => "libz",
18427 "move_panel" => "libpanel",
18428 "XOpenDisplay" => "libX11",
18429 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018430 "clock_gettime" => "librt",
18431 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018432);
18433
18434sub find_SymbolLibs($$)
18435{
18436 my ($LibVersion, $Symbol) = @_;
18437
18438 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18439 { # debug symbols
18440 return ();
18441 }
18442
18443 my %Paths = ();
18444
18445 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18446 {
18447 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18448 $Paths{$Path} = 1;
18449 }
18450 }
18451
18452 if(my $SymbolPrefix = getPrefix($Symbol))
18453 {
18454 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18455 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18456 }
18457
18458 if(not keys(%Paths))
18459 {
18460 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18461 {
18462 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18463 {
18464 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18465 $Paths{$Path} = 1;
18466 }
18467 }
18468 }
18469 }
18470
18471 if(not keys(%Paths))
18472 {
18473 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18474 {
18475 if($Symbol=~/\A$Prefix/)
18476 {
18477 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18478 {
18479 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18480 $Paths{$Path} = 1;
18481 }
18482 }
18483 }
18484 }
18485 }
18486
18487 if(not keys(%Paths))
18488 {
18489 if($SymbolPrefix)
18490 { # try to find a library by symbol prefix
18491 if($SymbolPrefix eq "inotify" and
18492 index($Symbol, "\@GLIBC")!=-1)
18493 {
18494 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18495 $Paths{$Path} = 1;
18496 }
18497 }
18498 else
18499 {
18500 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18501 $Paths{$Path} = 1;
18502 }
18503 }
18504 }
18505 }
18506
18507 if(my @Paths = keys(%Paths)) {
18508 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18509 }
18510 }
18511 return keys(%Paths);
18512}
18513
18514sub get_LibPath_Prefix($$)
18515{
18516 my ($LibVersion, $Prefix) = @_;
18517
18518 $Prefix = lc($Prefix);
18519 $Prefix=~s/[_]+\Z//g;
18520
18521 foreach ("-2", "2", "-1", "1", "")
18522 { # libgnome-2.so
18523 # libxml2.so
18524 # libdbus-1.so
18525 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18526 return $Path;
18527 }
18528 }
18529 return "";
18530}
18531
18532sub getPrefix($)
18533{
18534 my $Str = $_[0];
18535 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18536 { # XmuValidArea: Xmu
18537 return $1;
18538 }
18539 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18540 { # snfReadFont: snf
18541 return $1;
18542 }
18543 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18544 { # XRRTimes: XRR
18545 return $1;
18546 }
18547 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18548 { # H5HF_delete: H5
18549 return $1;
18550 }
18551 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18552 { # alarm_event_add: alarm_
18553 return $1;
18554 }
18555 elsif($Str=~/\A(([a-z])\2{1,})/i)
18556 { # ffopen
18557 return $1;
18558 }
18559 return "";
18560}
18561
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018562sub getSymbolSize($$)
18563{ # size from the shared library
18564 my ($Symbol, $LibVersion) = @_;
18565 return 0 if(not $Symbol);
18566 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18567 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18568 {
18569 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18570 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18571 {
18572 if($Size<0) {
18573 return -$Size;
18574 }
18575 }
18576 }
18577 return 0;
18578}
18579
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018580sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018581{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18582 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018583 my ($Name, $Type) = @_;
18584
18585 # single
18586 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018587 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018588 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018589 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018590 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018591
18592 # double
18593 if($Name=~/$DEFAULT_STD_PARMS/)
18594 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018595 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018596 {
18597 my ($ShortName, $FuncParams) = split_Signature($Name);
18598
18599 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18600 {
18601 if(index($FParam, "<")!=-1)
18602 {
18603 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18604 my $FParam_N = canonifyName($FParam, "T");
18605 if($FParam_N ne $FParam) {
18606 $Name=~s/\Q$FParam\E/$FParam_N/g;
18607 }
18608 }
18609 }
18610 }
18611 elsif($Type eq "T")
18612 {
18613 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18614
18615 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018616 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018617 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018618 my $FParam = $TParams[0];
18619 foreach my $Pos (1 .. $#TParams)
18620 {
18621 my $TParam = $TParams[$Pos];
18622 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18623 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18624 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018625 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018626 }
18627 }
18628 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018629 if($Type eq "S") {
18630 return formatName($Name, "S");
18631 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018632 return $Name;
18633}
18634
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018635sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018636{
18637 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018638 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018639 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018640 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018641 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018642 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018643 next if($tr_name{$Symbol});
18644 $Symbol=~s/[\@\$]+(.*)\Z//;
18645 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018646 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018647 elsif(index($Symbol, "?")==0)
18648 {
18649 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018650 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018651 }
18652 else
18653 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018654 $tr_name{$Symbol} = $Symbol;
18655 $mangled_name_gcc{$Symbol} = $Symbol;
18656 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018657 }
18658 }
18659 if($#MnglNames1 > -1)
18660 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018661 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018662 foreach my $MnglName (@MnglNames1)
18663 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018664 if(my $Unmangled = pop(@UnmangledNames))
18665 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018666 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018667 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18668 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18669 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018670 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018671 and $tr_name{$MnglName}=~/vtable for (.+)/)
18672 { # bind class name and v-table symbol
18673 my $ClassName = $1;
18674 $ClassVTable{$ClassName} = $MnglName;
18675 $VTableClass{$MnglName} = $ClassName;
18676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018677 }
18678 }
18679 }
18680 if($#MnglNames2 > -1)
18681 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018682 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018683 foreach my $MnglName (@MnglNames2)
18684 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018685 if(my $Unmangled = pop(@UnmangledNames))
18686 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018687 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018688 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018690 }
18691 }
18692 return \%tr_name;
18693}
18694
18695sub link_symbol($$$)
18696{
18697 my ($Symbol, $RunWith, $Deps) = @_;
18698 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18699 return 1;
18700 }
18701 if($Deps eq "+Deps")
18702 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018703 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018704 return 1;
18705 }
18706 }
18707 return 0;
18708}
18709
18710sub link_symbol_internal($$$)
18711{
18712 my ($Symbol, $RunWith, $Where) = @_;
18713 return 0 if(not $Where or not $Symbol);
18714 if($Where->{$RunWith}{$Symbol})
18715 { # the exact match by symbol name
18716 return 1;
18717 }
18718 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18719 { # indirect symbol version, i.e.
18720 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018721 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018722 if($Where->{$RunWith}{$VSym}) {
18723 return 1;
18724 }
18725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018726 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018727 if($Sym and $Ver)
18728 { # search for the symbol with the same version
18729 # or without version
18730 if($Where->{$RunWith}{$Sym})
18731 { # old: foo@v|foo@@v
18732 # new: foo
18733 return 1;
18734 }
18735 if($Where->{$RunWith}{$Sym."\@".$Ver})
18736 { # old: foo|foo@@v
18737 # new: foo@v
18738 return 1;
18739 }
18740 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18741 { # old: foo|foo@v
18742 # new: foo@@v
18743 return 1;
18744 }
18745 }
18746 return 0;
18747}
18748
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018749sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018750{
18751 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018752 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018753 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018754 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018755 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018756 my $NM = get_CmdPath("nm");
18757 if(not $NM) {
18758 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018759 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018760 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761 while(<APP>)
18762 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018763 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018764 push(@Imported, $1);
18765 }
18766 }
18767 close(APP);
18768 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018769 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018770 {
18771 my $DumpBinCmd = get_CmdPath("dumpbin");
18772 if(not $DumpBinCmd) {
18773 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18774 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018775 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018776 while(<APP>)
18777 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018778 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18779 push(@Imported, $1);
18780 }
18781 }
18782 close(APP);
18783 }
18784 else
18785 {
18786 my $ReadelfCmd = get_CmdPath("readelf");
18787 if(not $ReadelfCmd) {
18788 exitStatus("Not_Found", "can't find \"readelf\"");
18789 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018790 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018791 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018792 while(<APP>)
18793 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018794 if(defined $symtab)
18795 { # do nothing with symtab
18796 if(index($_, "'.dynsym'")!=-1)
18797 { # dynamic table
18798 $symtab = undef;
18799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018800 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018801 elsif(index($_, "'.symtab'")!=-1)
18802 { # symbol table
18803 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018804 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018805 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018806 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018807 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18808 if($Ndx eq "UND")
18809 { # only imported symbols
18810 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018811 }
18812 }
18813 }
18814 close(APP);
18815 }
18816 return @Imported;
18817}
18818
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018819my %ELF_BIND = map {$_=>1} (
18820 "WEAK",
18821 "GLOBAL"
18822);
18823
18824my %ELF_TYPE = map {$_=>1} (
18825 "FUNC",
18826 "IFUNC",
18827 "OBJECT",
18828 "COMMON"
18829);
18830
18831my %ELF_VIS = map {$_=>1} (
18832 "DEFAULT",
18833 "PROTECTED"
18834);
18835
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018836sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018837{ # read the line of 'readelf' output corresponding to the symbol
18838 my @Info = split(/\s+/, $_[0]);
18839 # Num: Value Size Type Bind Vis Ndx Name
18840 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018841 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018842 shift(@Info); # spaces
18843 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018844
18845 if($#Info==7)
18846 { # UND SYMBOL (N)
18847 if($Info[7]=~/\(\d+\)/) {
18848 pop(@Info);
18849 }
18850 }
18851
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018852 if($#Info!=6)
18853 { # other lines
18854 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018856 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018857 return () if(not defined $ELF_BIND{$Info[3]});
18858 return () if(not defined $ELF_VIS{$Info[4]});
18859 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18860 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18861 return ();
18862 }
18863 if($OStarget eq "symbian")
18864 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18865 if(index($Info[6], "_._.absent_export_")!=-1)
18866 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18867 return ();
18868 }
18869 $Info[6]=~s/\@.+//g; # remove version
18870 }
18871 if(index($Info[2], "0x") == 0)
18872 { # size == 0x3d158
18873 $Info[2] = hex($Info[2]);
18874 }
18875 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876}
18877
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018878sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018879{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880 my ($LibVersion, $Name) = @_;
18881 return "" if(not $LibVersion or not $Name);
18882 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18883 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018884 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018885 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18886}
18887
18888sub get_LibPath_I($$)
18889{
18890 my ($LibVersion, $Name) = @_;
18891 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018892 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018893 if(-f $Name)
18894 { # absolute path
18895 return $Name;
18896 }
18897 else
18898 { # broken
18899 return "";
18900 }
18901 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018902 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018903 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018904 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018905 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018906 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018907 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018908 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018909 }
18910 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18911 { # ldconfig default paths
18912 return $DefaultPath;
18913 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018914 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018915 { # search in default linker directories
18916 # and then in all system paths
18917 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018918 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018919 }
18920 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018921 if(not defined $Cache{"checkSystemFiles"}) {
18922 checkSystemFiles();
18923 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018924 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18925 return $AllObjects[0];
18926 }
18927 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18928 {
18929 if($ShortName ne $Name)
18930 { # FIXME: check this case
18931 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18932 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018933 }
18934 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018936 # can't find
18937 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018938}
18939
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018940sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018942 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18943 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018944
18945 my $Real_Path = realpath($Lib_Path);
18946
18947 if(not $Real_Path)
18948 { # broken link
18949 return ();
18950 }
18951
18952 my $Lib_Name = get_filename($Real_Path);
18953
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018954 if($ExtraInfo)
18955 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018956 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018957 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018958 }
18959
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018960 if($IsNeededLib)
18961 {
18962 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18963 return ();
18964 }
18965 }
18966 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018967 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018968
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018969 push(@RecurLib, $Lib_Name);
18970 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018971 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18972
18973 if(not $IsNeededLib)
18974 { # special cases: libstdc++ and libc
18975 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18976 {
18977 if($ShortName eq "libstdc++")
18978 { # libstdc++.so.6
18979 $STDCXX_TESTING = 1;
18980 }
18981 elsif($ShortName eq "libc")
18982 { # libc-2.11.3.so
18983 $GLIBC_TESTING = 1;
18984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018985 }
18986 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018987 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018988 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018989 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018990 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018991 mkpath(get_dirname($DebugPath));
18992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018993 if($OStarget eq "macos")
18994 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018995 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018996 if(not $NM) {
18997 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018998 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018999 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019000 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019001 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019002 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019003 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019004 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019005 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019006 else
19007 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019008 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019010 while(<LIB>)
19011 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019012 if($CheckUndefined)
19013 {
19014 if(not $IsNeededLib)
19015 {
19016 if(/ U _([\w\$]+)\s*\Z/)
19017 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019018 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019019 next;
19020 }
19021 }
19022 }
19023
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019024 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019025 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019026 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019027 if($IsNeededLib)
19028 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019029 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019030 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019031 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19032 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019034 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019035 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019036 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019037 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19038 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019039 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19040 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019041 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019042 setLanguage($LibVersion, "C++");
19043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045 }
19046 }
19047 }
19048 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019049
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019050 if($Deps)
19051 {
19052 if($LIB_TYPE eq "dynamic")
19053 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019054
19055 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019056 if(not $OtoolCmd) {
19057 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019058 }
19059
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019060 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19061 while(<LIB>)
19062 {
19063 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19064 and $1 ne $Lib_Path) {
19065 $NeededLib{$1} = 1;
19066 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019067 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019068 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019070 }
19071 }
19072 elsif($OStarget eq "windows")
19073 { # Windows *.dll, *.lib
19074 my $DumpBinCmd = get_CmdPath("dumpbin");
19075 if(not $DumpBinCmd) {
19076 exitStatus("Not_Found", "can't find \"dumpbin\"");
19077 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019078 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019079 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019080 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019081 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019082 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019083 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019084 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019085 else
19086 { # write to pipe
19087 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019089 while(<LIB>)
19090 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19091 # 1198 4AD SetThreadToken (forwarded to ...)
19092 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019093 # 1 0 00005B30 ??0?N = ... (with pdb)
19094 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019095 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019096 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019097 { # dynamic, static and forwarded symbols
19098 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019099 if($IsNeededLib)
19100 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019101 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019102 {
19103 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19104 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019107 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019108 {
19109 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19110 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019111 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19112 {
19113 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19114 setLanguage($LibVersion, "C++");
19115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019117 }
19118 }
19119 }
19120 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019121
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019122 if($Deps)
19123 {
19124 if($LIB_TYPE eq "dynamic")
19125 { # dependencies
19126 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19127 while(<LIB>)
19128 {
19129 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19130 and $1 ne $Lib_Path) {
19131 $NeededLib{path_format($1, $OSgroup)} = 1;
19132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019134 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019136 }
19137 }
19138 else
19139 { # Unix; *.so, *.a
19140 # Symbian: *.dso, *.lib
19141 my $ReadelfCmd = get_CmdPath("readelf");
19142 if(not $ReadelfCmd) {
19143 exitStatus("Not_Found", "can't find \"readelf\"");
19144 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019145 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019146 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019147 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019148 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019149 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019150 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019151 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019152 else
19153 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019154 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019155 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019156 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019157 while(<LIB>)
19158 {
19159 if($LIB_TYPE eq "dynamic")
19160 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019161 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019162 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019163 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019164 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019165 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019166 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019167 # do nothing with symtab
19168 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019170 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019172 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 next;
19174 }
19175 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019176 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019177 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019178 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019180 if($CheckUndefined)
19181 {
19182 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019183 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019184 }
19185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019186 next;
19187 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019188 if($Bind eq "WEAK")
19189 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019190 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019191 if($Weak eq "-Weak")
19192 { # skip WEAK symbols
19193 next;
19194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019195 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019196 my $Short = $Symbol;
19197 $Short=~s/\@.+//g;
19198 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019199 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019200 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19201 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019203 if($IsNeededLib)
19204 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019205 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019206 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019207 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19208 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019210 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019211 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019212 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019213 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19214 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19215 if($Vers)
19216 {
19217 if($LIB_EXT eq "so")
19218 { # value
19219 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19220 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019223 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19224 {
19225 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19226 setLanguage($LibVersion, "C++");
19227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019229 }
19230 }
19231 }
19232 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019233
19234 if($Deps and $LIB_TYPE eq "dynamic")
19235 { # dynamic library specifics
19236 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19237 open(LIB, $Cmd." |");
19238
19239 while(<LIB>)
19240 {
19241 if(/NEEDED.+\[([^\[\]]+)\]/)
19242 { # dependencies:
19243 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19244 $NeededLib{$1} = 1;
19245 }
19246 }
19247
19248 close(LIB);
19249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019251 if($Vers)
19252 {
19253 if(not $IsNeededLib and $LIB_EXT eq "so")
19254 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019255 my %Found = ();
19256
19257 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019258 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019259 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019260 next if(index($Symbol,"\@")==-1);
19261 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019262 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019263 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019264 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019265 if($Symbol_SameValue ne $Symbol
19266 and index($Symbol_SameValue,"\@")==-1)
19267 {
19268 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019269 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019270 last;
19271 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019272 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019273 }
19274 }
19275
19276 # default
19277 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19278 {
19279 next if(defined $Found{$Symbol});
19280 next if(index($Symbol,"\@\@")==-1);
19281
19282 if($Symbol=~/\A([^\@]*)\@\@/
19283 and not $SymVer{$LibVersion}{$1})
19284 {
19285 $SymVer{$LibVersion}{$1} = $Symbol;
19286 $Found{$Symbol} = 1;
19287 }
19288 }
19289
19290 # non-default
19291 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19292 {
19293 next if(defined $Found{$Symbol});
19294 next if(index($Symbol,"\@")==-1);
19295
19296 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19297 and not $SymVer{$LibVersion}{$1})
19298 {
19299 $SymVer{$LibVersion}{$1} = $Symbol;
19300 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019301 }
19302 }
19303 }
19304 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019305 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019306 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019307 foreach my $DyLib (sort keys(%NeededLib))
19308 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019309 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19310
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019311 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19312 {
19313 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19314 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19315 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019317 }
19318 }
19319 pop(@RecurLib);
19320 return $Library_Symbol{$LibVersion};
19321}
19322
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019323sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019324{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019325 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019326 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019327 return keys(%Prefixes);
19328}
19329
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019330sub get_prefixes_I($$)
19331{
19332 foreach my $P (@{$_[0]})
19333 {
19334 my @Parts = reverse(split(/[\/\\]+/, $P));
19335 my $Name = $Parts[0];
19336 foreach (1 .. $#Parts)
19337 {
19338 $_[1]->{$Name}{$P} = 1;
19339 last if($_>4 or $Parts[$_] eq "include");
19340 $Name = $Parts[$_].$SLASH.$Name;
19341 }
19342 }
19343}
19344
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019345sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019346{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019347 $Cache{"checkSystemFiles"} = 1;
19348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019349 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019350
19351 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019352 {
19353 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019354
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019355 my @Files = cmd_find($DevelPath,"f");
19356 foreach my $Link (cmd_find($DevelPath,"l"))
19357 { # add symbolic links
19358 if(-f $Link) {
19359 push(@Files, $Link);
19360 }
19361 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019362
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019363 # search for headers in /usr/lib
19364 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19365 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19366 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019367
19368 # search for libraries in /usr/lib (including symbolic links)
19369 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19370 foreach my $Path (@Libs)
19371 {
19372 my $N = get_filename($Path);
19373 $SystemObjects{$N}{$Path} = 1;
19374 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019375 }
19376 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019377
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019378 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019379 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019380 next if(not -d $DevelPath);
19381 # search for all header files in the /usr/include
19382 # with or without extension (ncurses.h, QtCore, ...)
19383 push(@SysHeaders, cmd_find($DevelPath,"f"));
19384 foreach my $Link (cmd_find($DevelPath,"l"))
19385 { # add symbolic links
19386 if(-f $Link) {
19387 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019389 }
19390 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019391 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019392}
19393
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019394sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019395{
19396 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019397 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019398 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19399 {
19400 if(not -e $Dest) {
19401 exitStatus("Access_Error", "can't access \'$Dest\'");
19402 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019403 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019404 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19405 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019406 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019407 }
19408 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019409 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019410}
19411
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019412sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019413{
19414 my ($Path, $LibVersion) = @_;
19415 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019416 my $Name = get_filename($Path);
19417 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019418 return 1;
19419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019420 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019421 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19422 return 1;
19423 }
19424 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19425 {
19426 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19427 return 1;
19428 }
19429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019430 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019431 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019432 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019433 return 1;
19434 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019435 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 return 1;
19437 }
19438 }
19439 return 0;
19440}
19441
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019442sub specificHeader($$)
19443{
19444 my ($Header, $Spec) = @_;
19445 my $Name = get_filename($Header);
19446
19447 if($Spec eq "windows")
19448 {# MS Windows
19449 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19450 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19451 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19452 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19453 my @Dirs = (
19454 "win32",
19455 "win64",
19456 "win",
19457 "windows",
19458 "msvcrt"
19459 ); # /gsf-win32/
19460 if(my $DIRs = join("|", @Dirs)) {
19461 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19462 }
19463 }
19464 elsif($Spec eq "macos")
19465 { # Mac OS
19466 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19467 }
19468
19469 return 0;
19470}
19471
19472sub skipAlienHeader($)
19473{
19474 my $Path = $_[0];
19475 my $Name = get_filename($Path);
19476 my $Dir = get_dirname($Path);
19477
19478 if($Tolerance=~/2/)
19479 { # 2 - skip internal headers
19480 my @Terms = (
19481 "p",
19482 "priv",
19483 "int",
19484 "impl",
19485 "implementation",
19486 "internal",
19487 "private",
19488 "old",
19489 "compat",
19490 "debug",
19491 "test",
19492 "gen"
19493 );
19494
19495 my @Dirs = (
19496 "private",
19497 "priv",
19498 "port",
19499 "impl",
19500 "internal",
19501 "detail",
19502 "details",
19503 "old",
19504 "compat",
19505 "debug",
19506 "config",
19507 "compiler",
19508 "platform",
19509 "test"
19510 );
19511
19512 if(my $TERMs = join("|", @Terms)) {
19513 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19514 }
19515 if(my $DIRs = join("|", @Dirs)) {
19516 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19517 }
19518
19519 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19520 }
19521
19522 if($Tolerance=~/1/)
19523 { # 1 - skip non-Linux headers
19524 if($OSgroup ne "windows")
19525 {
19526 if(specificHeader($Path, "windows")) {
19527 return 1;
19528 }
19529 }
19530 if($OSgroup ne "macos")
19531 {
19532 if(specificHeader($Path, "macos")) {
19533 return 1;
19534 }
19535 }
19536 }
19537
19538 # valid
19539 return 0;
19540}
19541
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019542sub skipHeader($$)
19543{
19544 my ($Path, $LibVersion) = @_;
19545 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019546 if(defined $Cache{"skipHeader"}{$Path}) {
19547 return $Cache{"skipHeader"}{$Path};
19548 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019549 if(defined $Tolerance and $Tolerance=~/1|2/)
19550 { # --tolerant
19551 if(skipAlienHeader($Path)) {
19552 return ($Cache{"skipHeader"}{$Path} = 1);
19553 }
19554 }
19555 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19556 return 0;
19557 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019558 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19559}
19560
19561sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019562{ # returns:
19563 # 1 - if header should NOT be included and checked
19564 # 2 - if header should NOT be included, but should be checked
19565 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019566 my $Name = get_filename($Path);
19567 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019568 return $Kind;
19569 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019570 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19571 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019572 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019573 if(index($Path, $D)!=-1)
19574 {
19575 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19576 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019578 }
19579 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019580 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19581 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019582 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019583 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19584 {
19585 if($Name=~/$P/) {
19586 return $Kind;
19587 }
19588 if($P=~/[\/\\]/ and $Path=~/$P/) {
19589 return $Kind;
19590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019591 }
19592 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019593
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019594 return 0;
19595}
19596
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019597sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019598{
19599 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019600 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019601 { # system directory
19602 return;
19603 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019604 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605 { # already registered
19606 return;
19607 }
19608 foreach my $Path (find_libs($Dir,"",1))
19609 {
19610 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019611 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019612 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019613 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019614 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19615}
19616
19617sub registerObject($$)
19618{
19619 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019620
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019621 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019622 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019623 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019624 {
19625 if(my $SONAME = getSONAME($Path)) {
19626 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19627 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019628 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019629 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19630 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019631 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019632
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019633 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019634 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019635 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019636 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019637 if($ObjArch ne getArch_GCC($LibVersion))
19638 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19639 $CheckedArch{$LibVersion} = 1;
19640 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 +040019641 }
19642 }
19643 }
19644}
19645
19646sub getArch_Object($)
19647{
19648 my $Path = $_[0];
19649
19650 my %MachineType = (
19651 "14C" => "x86",
19652 "8664" => "x86_64",
19653 "1C0" => "arm",
19654 "200" => "ia64"
19655 );
19656
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019657 my %ArchName = (
19658 "s390:31-bit" => "s390",
19659 "s390:64-bit" => "s390x",
19660 "powerpc:common" => "ppc32",
19661 "powerpc:common64" => "ppc64",
19662 "i386:x86-64" => "x86_64",
19663 "mips:3000" => "mips",
19664 "sparc:v8plus" => "sparcv9"
19665 );
19666
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019667 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019668 {
19669 my $DumpbinCmd = get_CmdPath("dumpbin");
19670 if(not $DumpbinCmd) {
19671 exitStatus("Not_Found", "can't find \"dumpbin\"");
19672 }
19673
19674 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19675 my $Out = `$Cmd`;
19676
19677 if($Out=~/(\w+)\smachine/)
19678 {
19679 if(my $Type = $MachineType{uc($1)})
19680 {
19681 return $Type;
19682 }
19683 }
19684 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019685 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019686 {
19687 my $ObjdumpCmd = get_CmdPath("objdump");
19688 if(not $ObjdumpCmd) {
19689 exitStatus("Not_Found", "can't find \"objdump\"");
19690 }
19691
19692 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019693
19694 if($OSgroup eq "windows") {
19695 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19696 }
19697 else {
19698 $Cmd = "LANG=$LOCALE ".$Cmd;
19699 }
19700 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019701
19702 if($Out=~/architecture:\s+([\w\-\:]+)/)
19703 {
19704 my $Arch = $1;
19705 if($Arch=~s/\:(.+)//)
19706 {
19707 my $Suffix = $1;
19708
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019709 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019710 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019711 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019712 }
19713 }
19714
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019715 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019716 $Arch = "x86";
19717 }
19718
19719 if($Arch eq "x86-64") {
19720 $Arch = "x86_64";
19721 }
19722
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019723 if($Arch eq "ia64-elf64") {
19724 $Arch = "ia64";
19725 }
19726
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019727 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019728 }
19729 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019730 elsif($OStarget=~/macos/)
19731 {
19732 my $OtoolCmd = get_CmdPath("otool");
19733 if(not $OtoolCmd) {
19734 exitStatus("Not_Found", "can't find \"otool\"");
19735 }
19736
19737 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19738 my $Out = qx/$Cmd/;
19739
19740 if($Out=~/X86_64/i) {
19741 return "x86_64";
19742 }
19743 elsif($Out=~/X86/i) {
19744 return "x86";
19745 }
19746 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019747 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019748 {
19749 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019750 # TODO
19751 }
19752
19753 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019754}
19755
19756sub getSONAME($)
19757{
19758 my $Path = $_[0];
19759 return if(not $Path);
19760 if(defined $Cache{"getSONAME"}{$Path}) {
19761 return $Cache{"getSONAME"}{$Path};
19762 }
19763 my $ObjdumpCmd = get_CmdPath("objdump");
19764 if(not $ObjdumpCmd) {
19765 exitStatus("Not_Found", "can't find \"objdump\"");
19766 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019767 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019768 if($OSgroup eq "windows") {
19769 $SonameCmd .= " | find \"SONAME\"";
19770 }
19771 else {
19772 $SonameCmd .= " | grep SONAME";
19773 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019774 if(my $SonameInfo = `$SonameCmd`)
19775 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019776 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19777 return ($Cache{"getSONAME"}{$Path} = $1);
19778 }
19779 }
19780 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019781}
19782
19783sub getSOPaths_Dest($$)
19784{
19785 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019786 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019787 return ();
19788 }
19789 if(-f $Dest)
19790 {
19791 if(not parse_libname($Dest, "name", $OStarget)) {
19792 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19793 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019794 registerObject($Dest, $LibVersion);
19795 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019796 return ($Dest);
19797 }
19798 elsif(-d $Dest)
19799 {
19800 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019801 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019802 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019803 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19804 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019805 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019806 { # all files and symlinks that match the name of a library
19807 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19808 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019809 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019810 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019811 }
19812 }
19813 }
19814 else
19815 { # search for all files and symlinks
19816 foreach my $Path (find_libs($Dest,"",""))
19817 {
19818 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019819 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019820 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019821 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019822 }
19823 if($OSgroup eq "macos")
19824 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019825 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019826 {
19827 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019828 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019829 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019830 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19831 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019832 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019833 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019834 }
19835 }
19836 }
19837 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019838 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019839 }
19840 else {
19841 return ();
19842 }
19843}
19844
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019845sub isCyclical($$)
19846{
19847 my ($Stack, $Value) = @_;
19848 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019849}
19850
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019851sub getGCC_Opts($)
19852{ # to use in module
19853 my $LibVersion = $_[0];
19854
19855 my @Opts = ();
19856
19857 if($CompilerOptions{$LibVersion})
19858 { # user-defined options
19859 push(@Opts, $CompilerOptions{$LibVersion});
19860 }
19861 if($GccOptions)
19862 { # additional
19863 push(@Opts, $GccOptions);
19864 }
19865
19866 if(@Opts) {
19867 return join(" ", @Opts);
19868 }
19869
19870 return undef;
19871}
19872
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019873sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019874{
19875 my $LibVersion = $_[0];
19876
19877 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19878 return $Cache{"getArch_GCC"}{$LibVersion};
19879 }
19880
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019881 if(not $GCC_PATH) {
19882 return undef;
19883 }
19884
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019885 my $Arch = undef;
19886
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019887 if(my $Target = get_dumpmachine($GCC_PATH))
19888 {
19889 if($Target=~/x86_64/) {
19890 $Arch = "x86_64";
19891 }
19892 elsif($Target=~/i[3-6]86/) {
19893 $Arch = "x86";
19894 }
19895 elsif($Target=~/\Aarm/i) {
19896 $Arch = "arm";
19897 }
19898 }
19899
19900 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019901 {
19902 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19903
19904 my $Cmd = $GCC_PATH." test.c -o test";
19905 if(my $Opts = getGCC_Opts($LibVersion))
19906 { # user-defined options
19907 $Cmd .= " ".$Opts;
19908 }
19909
19910 chdir($TMP_DIR);
19911 system($Cmd);
19912 chdir($ORIG_DIR);
19913
19914 $Arch = getArch_Object("$TMP_DIR/test");
19915
19916 unlink("$TMP_DIR/test.c");
19917 unlink("$TMP_DIR/test");
19918 }
19919
19920 if(not $Arch) {
19921 exitStatus("Error", "can't check ARCH type");
19922 }
19923
19924 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19925}
19926
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019927sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019928{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019929 my $LibVersion = $_[0];
19930
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019931 my $Size = undef;
19932
19933 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019934 if(my $Arch = getArch($LibVersion))
19935 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019936 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019937 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019938 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019939 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19940 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019941 }
19942 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019943
19944 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019945 {
19946 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019947
19948 my $Cmd = $GCC_PATH." -E -dD empty.h";
19949 if(my $Opts = getGCC_Opts($LibVersion))
19950 { # user-defined options
19951 $Cmd .= " ".$Opts;
19952 }
19953
19954 chdir($TMP_DIR);
19955 my $Defines = `$Cmd`;
19956 chdir($ORIG_DIR);
19957
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019958 unlink("$TMP_DIR/empty.h");
19959
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019960 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19961 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019962 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019963 }
19964 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19965 { # GCC 3
19966 my $PTRDIFF = $1;
19967 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019968 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019969 }
19970 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019971 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019972 }
19973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019974 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019975
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019976 if(not $Size) {
19977 exitStatus("Error", "can't check WORD size");
19978 }
19979
19980 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019981}
19982
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019983sub getWordSize($)
19984{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019985 return $WORD_SIZE{$_[0]};
19986}
19987
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019988sub majorVersion($)
19989{
19990 my $V = $_[0];
19991 return 0 if(not $V);
19992 my @VParts = split(/\./, $V);
19993 return $VParts[0];
19994}
19995
19996sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019997{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019998 my ($V1, $V2) = @_;
19999 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020000 my @V1Parts = split(/\./, $V1);
20001 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020002 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20003 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020004 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20005 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20006 }
20007 return -1 if($#V1Parts < $#V2Parts);
20008 return 1 if($#V1Parts > $#V2Parts);
20009 return 0;
20010}
20011
20012sub read_ABI_Dump($$)
20013{
20014 my ($LibVersion, $Path) = @_;
20015 return if(not $LibVersion or not -e $Path);
20016 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020017 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020018 { # input *.abi
20019 $FilePath = $Path;
20020 }
20021 else
20022 { # input *.abi.tar.gz
20023 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020024 if(not isDump_U($FilePath)) {
20025 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020027 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020028
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020029 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020030
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020031 my $Line = readLineNum($FilePath, 0);
20032 if($Line=~/xml/)
20033 { # XML format
20034 loadModule("XmlDump");
20035 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020037 else
20038 { # Perl Data::Dumper format (default)
20039 open(DUMP, $FilePath);
20040 local $/ = undef;
20041 my $Content = <DUMP>;
20042 close(DUMP);
20043
20044 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20045 { # remove temp file
20046 unlink($FilePath);
20047 }
20048 if($Content!~/};\s*\Z/) {
20049 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20050 }
20051 $ABI = eval($Content);
20052 if(not $ABI) {
20053 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020055 }
20056 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020057 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020058 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020059 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020060 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020061 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020062 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020063 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020064 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020065
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020066 if($ABI->{"PublicABI"}) {
20067 $UsedDump{$LibVersion}{"Public"} = 1;
20068 }
20069
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020070 if($ABI->{"ABI_DUMP_VERSION"})
20071 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020072 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020073 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020074 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020075 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020076 }
20077 else
20078 { # support for old ABI dumps
20079 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020080 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020081 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020082 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020083 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020084
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020085 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020086 {
20087 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 +040020088 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020089
20090 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20091 { # DWARF ABI Dump
20092 $UseConv_Real{$LibVersion}{"P"} = 1;
20093 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20094
20095 $UsedDump{$LibVersion}{"DWARF"} = 1;
20096
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020097 if(not $TargetComponent_Opt)
20098 {
20099 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20100 $TargetComponent = "module";
20101 }
20102 else {
20103 $TargetComponent = "object";
20104 }
20105 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020106 }
20107
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020108 if(not checkDump($LibVersion, "2.11"))
20109 { # old ABI dumps
20110 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020111 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020112 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020113 { # ABI dump created with --binary option
20114 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20115 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020116 else
20117 { # default
20118 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20119 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020120
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020121 if(defined $ABI->{"Mode"}
20122 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 { # --ext option
20124 $ExtendedCheck = 1;
20125 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020126 if($ABI->{"Extra"}) {
20127 $ExtraDump = 1;
20128 }
20129
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020130 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020131 {
20132 $UsedDump{$LibVersion}{"L"} = $Lang;
20133 setLanguage($LibVersion, $Lang);
20134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020135 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020136 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020137 }
20138 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020139 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020140 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020141 if(not $TInfo)
20142 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020143 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020144 }
20145 my %Tid_TDid = ();
20146 foreach my $TDid (keys(%{$TInfo}))
20147 {
20148 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20149 {
20150 $MAX_ID = $Tid if($Tid>$MAX_ID);
20151 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020152 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020153 }
20154 }
20155 my %NewID = ();
20156 foreach my $Tid (keys(%Tid_TDid))
20157 {
20158 my @TDids = keys(%{$Tid_TDid{$Tid}});
20159 if($#TDids>=1)
20160 {
20161 foreach my $TDid (@TDids)
20162 {
20163 if($TDid) {
20164 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20165 }
20166 else
20167 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020168 my $ID = ++$MAX_ID;
20169
20170 $NewID{$TDid}{$Tid} = $ID;
20171 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20172 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020173 }
20174 }
20175 }
20176 else
20177 {
20178 my $TDid = $TDids[0];
20179 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20180 }
20181 }
20182 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20183 {
20184 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20185 if(defined $Info{"BaseType"})
20186 {
20187 my $Bid = $Info{"BaseType"}{"Tid"};
20188 my $BDid = $Info{"BaseType"}{"TDid"};
20189 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020190 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020191 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20192 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20193 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020194 }
20195 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020197 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020198 read_Machine_DumpInfo($ABI, $LibVersion);
20199 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020200 if(not $SymbolInfo{$LibVersion})
20201 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020202 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020203 }
20204 if(not keys(%{$SymbolInfo{$LibVersion}}))
20205 { # validation of old-version dumps
20206 if(not $ExtendedCheck) {
20207 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20208 }
20209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020210 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020211 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020212 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020213 else
20214 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020215 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020216 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020217 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020218 }
20219 if(not $DepSymbols)
20220 { # Cannot reconstruct DepSymbols. This may result in false
20221 # positives if the old dump is for library 2. Not a problem if
20222 # old dumps are only from old libraries.
20223 $DepSymbols = {};
20224 }
20225 foreach my $Symbol (keys(%{$DepSymbols})) {
20226 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020228 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020229 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020230
20231 if(my $V = $TargetVersion{$LibVersion}) {
20232 $Descriptor{$LibVersion}{"Version"} = $V;
20233 }
20234 else {
20235 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20236 }
20237
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020238 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020239 { # if not defined by -skip-types option
20240 if(defined $ABI->{"SkipTypes"})
20241 {
20242 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20243 {
20244 $SkipTypes{$LibVersion}{$TName} = 1;
20245 }
20246 }
20247 if(defined $ABI->{"OpaqueTypes"})
20248 { # support for old dumps
20249 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20250 {
20251 $SkipTypes{$LibVersion}{$TName} = 1;
20252 }
20253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020254 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020256 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020257 { # if not defined by -skip-symbols option
20258 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20259 if(not $SkipSymbols{$LibVersion})
20260 { # support for old dumps
20261 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20262 }
20263 if(not $SkipSymbols{$LibVersion})
20264 { # support for old dumps
20265 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020267 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020268 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020269
20270 if(not $TargetHeaders{$LibVersion})
20271 { # if not defined by -headers-list option
20272 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20273 }
20274
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020275 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020276 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020277 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020278
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020279 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020280 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020281 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020282
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020283 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020284 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020285
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020286 if(not checkDump($LibVersion, "2.10.1")
20287 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020288 { # support for old ABI dumps: added target headers
20289 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020290 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020291 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020292
20293 if(not $ABI->{"PublicABI"})
20294 {
20295 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20296 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20297 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020299 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020300 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020301 if(defined $ABI->{"GccConstants"})
20302 { # 3.0
20303 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20304 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20305 }
20306 }
20307
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020308 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020309 if(not $NestedNameSpaces{$LibVersion})
20310 { # support for old dumps
20311 # Cannot reconstruct NameSpaces. This may affect design
20312 # of the compatibility report.
20313 $NestedNameSpaces{$LibVersion} = {};
20314 }
20315 # target system type
20316 # needed to adopt HTML report
20317 if(not $DumpSystem)
20318 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020319 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020320 }
20321 # recreate environment
20322 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20323 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020324 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020326 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20327 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020328 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020329 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020330 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020331 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20332 {
20333 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20334 setLanguage($LibVersion, "C++");
20335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020336 }
20337 }
20338 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020339 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20340 {
20341 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20342 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20343 }
20344 }
20345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020347 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020348 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020349 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020350 {
20351 if(not $Symbol_Library{$LibVersion}{$MnglName}
20352 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20353 push(@VFunc, $MnglName);
20354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020355 }
20356 }
20357 translateSymbols(@VFunc, $LibVersion);
20358 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020359 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20360
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020361 if(not checkDump($LibVersion, "3.0"))
20362 { # support for old ABI dumps
20363 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20364 {
20365 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20366 {
20367 if(ref($BaseType) eq "HASH") {
20368 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20369 }
20370 }
20371 }
20372 }
20373
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020374 if(not checkDump($LibVersion, "3.2"))
20375 { # support for old ABI dumps
20376 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20377 {
20378 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20379 {
20380 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20381 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20382 }
20383 }
20384 }
20385
20386 # repair target headers list
20387 delete($TargetHeaders{$LibVersion});
20388 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020389 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20390 }
20391 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20392 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020393 }
20394
20395 # non-target constants from anon enums
20396 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20397 {
20398 if(not $ExtraDump
20399 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20400 {
20401 delete($Constants{$LibVersion}{$Name});
20402 }
20403 }
20404 }
20405
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020406 if(not checkDump($LibVersion, "2.20"))
20407 { # support for old ABI dumps
20408 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20409 {
20410 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20411
20412 if($TType=~/Struct|Union|Enum|Typedef/)
20413 { # repair complex types first
20414 next;
20415 }
20416
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020417 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020418 {
20419 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20420 if($BType=~/Struct|Union|Enum/i)
20421 {
20422 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20423 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20424 }
20425 }
20426 }
20427 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20428 {
20429 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20430 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20431 if($TType=~/Struct|Union|Enum/) {
20432 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20433 }
20434 }
20435 }
20436
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020437 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020438 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020439 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20440 { # support for old ABI dumps < 2.0 (ACC 1.22)
20441 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20442 {
20443 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20444 {
20445 if($Access ne "public") {
20446 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20447 }
20448 }
20449 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20450 }
20451 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020453 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20454 { # support for old ABI dumps
20455 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20456 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020457 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20458 { # DWARF ABI Dumps
20459 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20460 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020461 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20462 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20463 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020464
20465 # support for old formatting of type names
20466 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20467
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020468 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20469 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020470 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020471 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20472 {
20473 if($SubId eq $TypeId)
20474 { # Fix erroneus ABI dump
20475 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20476 next;
20477 }
20478
20479 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020480 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020481 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020482 if($TInfo{"Type"} eq "MethodPtr")
20483 {
20484 if(defined $TInfo{"Param"})
20485 { # support for old ABI dumps <= 1.17
20486 if(not defined $TInfo{"Param"}{"0"})
20487 {
20488 my $Max = keys(%{$TInfo{"Param"}});
20489 foreach my $Pos (1 .. $Max) {
20490 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20491 }
20492 delete($TInfo{"Param"}{$Max});
20493 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20494 }
20495 }
20496 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020497 if($TInfo{"BaseType"} eq $TypeId)
20498 { # fix ABI dump
20499 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20500 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020501
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020502 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020503 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020504 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020505 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020506 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20507 if(not $BName)
20508 { # broken type
20509 next;
20510 }
20511 if($TInfo{"Name"} eq $BName)
20512 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020513 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020514 next;
20515 }
20516 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20517 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020518 }
20519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020520 }
20521 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20522 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020523 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020524 }
20525 }
20526
20527 if(not checkDump($LibVersion, "2.15"))
20528 { # support for old ABI dumps
20529 my %Dups = ();
20530 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20531 {
20532 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020533 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020534 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20535 { # remove template decls
20536 delete($SymbolInfo{$LibVersion}{$InfoId});
20537 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020539 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020540 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20541 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020542 { # templates
20543 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020544 }
20545 }
20546 }
20547
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020548 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20549 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020550 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20551 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20552 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20553 { # support for old ABI dumps (< 3.1)
20554 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20555 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20556 { # add "this" first parameter
20557 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20558 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20559
20560 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20561 {
20562 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20563 foreach my $Pos (reverse(0 .. $#Pos)) {
20564 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20565 }
20566 }
20567 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20568 }
20569 }
20570
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020571 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20572 { # ABI dumps have no mangled names for C-functions
20573 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20574 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020575 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20576 { # support for old ABI dumps
20577 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20578 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020579 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20580 { # DWARF ABI Dumps
20581 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20582 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020583 }
20584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020585 $Descriptor{$LibVersion}{"Dump"} = 1;
20586}
20587
20588sub read_Machine_DumpInfo($$)
20589{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020590 my ($ABI, $LibVersion) = @_;
20591 if($ABI->{"Arch"}) {
20592 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020593 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020594 if($ABI->{"WordSize"}) {
20595 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020596 }
20597 else
20598 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020599 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020600 }
20601 if(not $WORD_SIZE{$LibVersion})
20602 { # support for old dumps (<1.23)
20603 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20604 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020605 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020606 }
20607 else
20608 {
20609 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020610 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020611 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020612 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20613 { # any "pointer"-type
20614 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020615 last;
20616 }
20617 }
20618 if($PSize)
20619 { # a pointer type size
20620 $WORD_SIZE{$LibVersion} = $PSize;
20621 }
20622 else {
20623 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20624 }
20625 }
20626 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020627 if($ABI->{"GccVersion"}) {
20628 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020629 }
20630}
20631
20632sub read_Libs_DumpInfo($$)
20633{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020634 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020635 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20636 if(not $Library_Symbol{$LibVersion})
20637 { # support for old dumps
20638 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020640 if(keys(%{$Library_Symbol{$LibVersion}})
20641 and not $DumpAPI) {
20642 $Descriptor{$LibVersion}{"Libs"} = "OK";
20643 }
20644}
20645
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020646sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020647{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020648 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020649
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020650 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020651 and not $DumpAPI) {
20652 $Descriptor{$LibVersion}{"Headers"} = "OK";
20653 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020654 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020655 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020656 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020657 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020658 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020659
20660 if(keys(%{$ABI->{"Sources"}})
20661 and not $DumpAPI) {
20662 $Descriptor{$LibVersion}{"Sources"} = "OK";
20663 }
20664 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020665 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020666 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20667 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020669}
20670
20671sub find_libs($$$)
20672{
20673 my ($Path, $Type, $MaxDepth) = @_;
20674 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020675 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020676}
20677
20678sub createDescriptor($$)
20679{
20680 my ($LibVersion, $Path) = @_;
20681 if(not $LibVersion or not $Path
20682 or not -e $Path) {
20683 return "";
20684 }
20685 if(-d $Path)
20686 { # directory with headers files and shared objects
20687 return "
20688 <version>
20689 ".$TargetVersion{$LibVersion}."
20690 </version>
20691
20692 <headers>
20693 $Path
20694 </headers>
20695
20696 <libs>
20697 $Path
20698 </libs>";
20699 }
20700 else
20701 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020702 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020703 { # standard XML-descriptor
20704 return readFile($Path);
20705 }
20706 elsif(is_header($Path, 2, $LibVersion))
20707 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020708 $CheckHeadersOnly = 1;
20709
20710 if($LibVersion==1) {
20711 $TargetVersion{$LibVersion} = "X";
20712 }
20713
20714 if($LibVersion==2) {
20715 $TargetVersion{$LibVersion} = "Y";
20716 }
20717
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020718 return "
20719 <version>
20720 ".$TargetVersion{$LibVersion}."
20721 </version>
20722
20723 <headers>
20724 $Path
20725 </headers>
20726
20727 <libs>
20728 none
20729 </libs>";
20730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020731 else
20732 { # standard XML-descriptor
20733 return readFile($Path);
20734 }
20735 }
20736}
20737
20738sub detect_lib_default_paths()
20739{
20740 my %LPaths = ();
20741 if($OSgroup eq "bsd")
20742 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020743 if(my $LdConfig = get_CmdPath("ldconfig"))
20744 {
20745 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20746 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020747 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20748 {
20749 my $Name = "lib".$1;
20750 if(not defined $LPaths{$Name}) {
20751 $LPaths{$Name} = $2;
20752 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020753 }
20754 }
20755 }
20756 else {
20757 printMsg("WARNING", "can't find ldconfig");
20758 }
20759 }
20760 else
20761 {
20762 if(my $LdConfig = get_CmdPath("ldconfig"))
20763 {
20764 if($SystemRoot and $OSgroup eq "linux")
20765 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20766 if(-e $SystemRoot."/etc/ld.so.conf") {
20767 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20768 }
20769 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020770 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20771 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20773 {
20774 my ($Name, $Path) = ($1, $2);
20775 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020776 if(not defined $LPaths{$Name})
20777 { # get first element from the list of available paths
20778
20779 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20780 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20781 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20782
20783 $LPaths{$Name} = $Path;
20784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 }
20786 }
20787 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020788 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020789 printMsg("WARNING", "can't find ldconfig");
20790 }
20791 }
20792 return \%LPaths;
20793}
20794
20795sub detect_bin_default_paths()
20796{
20797 my $EnvPaths = $ENV{"PATH"};
20798 if($OSgroup eq "beos") {
20799 $EnvPaths.=":".$ENV{"BETOOLS"};
20800 }
20801 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020802 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020803 {
20804 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020805 next if(not $Path);
20806 if($SystemRoot
20807 and $Path=~/\A\Q$SystemRoot\E\//)
20808 { # do NOT use binaries from target system
20809 next;
20810 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020811 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020812 }
20813}
20814
20815sub detect_inc_default_paths()
20816{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020817 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020818 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020819 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020820 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020821 next if(index($Line, "/cc1plus ")!=-1);
20822
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020823 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20824 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020825 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020826 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020827 if(index($Path, "c++")!=-1
20828 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020829 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020830 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020831 if(not defined $MAIN_CPP_DIR
20832 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20833 $MAIN_CPP_DIR = $Path;
20834 }
20835 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020836 elsif(index($Path, "gcc")!=-1) {
20837 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020838 }
20839 else
20840 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020841 if($Path=~/local[\/\\]+include/)
20842 { # local paths
20843 next;
20844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020845 if($SystemRoot
20846 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20847 { # The GCC include path for user headers is not a part of the system root
20848 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20849 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20850 next;
20851 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020852 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020853 }
20854 }
20855 }
20856 unlink("$TMP_DIR/empty.h");
20857 return %DPaths;
20858}
20859
20860sub detect_default_paths($)
20861{
20862 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20863 my $Search = $_[0];
20864 if($Search!~/inc/) {
20865 $HSearch = 0;
20866 }
20867 if($Search!~/lib/) {
20868 $LSearch = 0;
20869 }
20870 if($Search!~/bin/) {
20871 $BSearch = 0;
20872 }
20873 if($Search!~/gcc/) {
20874 $GSearch = 0;
20875 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020876 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020877 { # <search_headers> section of the XML descriptor
20878 # do NOT search for systems headers
20879 $HSearch = 0;
20880 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020881 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020882 { # <search_libs> section of the XML descriptor
20883 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020884 $LSearch = 0;
20885 }
20886 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20887 { # additional search paths
20888 next if($Type eq "include" and not $HSearch);
20889 next if($Type eq "lib" and not $LSearch);
20890 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020891 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020892 }
20893 if($OSgroup ne "windows")
20894 { # unix-like
20895 foreach my $Type ("include", "lib", "bin")
20896 { # automatic detection of system "devel" directories
20897 next if($Type eq "include" and not $HSearch);
20898 next if($Type eq "lib" and not $LSearch);
20899 next if($Type eq "bin" and not $BSearch);
20900 my ($UsrDir, $RootDir) = ("/usr", "/");
20901 if($SystemRoot and $Type ne "bin")
20902 { # 1. search for target headers and libraries
20903 # 2. use host commands: ldconfig, readelf, etc.
20904 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20905 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020906 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020907 if(-d $RootDir."/".$Type)
20908 { # if "/lib" is symbolic link
20909 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020910 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020911 }
20912 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020913 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020914 }
20915 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020916 if(-d $UsrDir)
20917 {
20918 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020919 if(-d $UsrDir."/".$Type)
20920 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020921 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922 }
20923 }
20924 }
20925 }
20926 if($BSearch)
20927 {
20928 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020929 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020930 }
20931 # check environment variables
20932 if($OSgroup eq "beos")
20933 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020934 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020935 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020936 if($_ eq ".") {
20937 next;
20938 }
20939 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20940 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20941 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020942 }
20943 }
20944 if($HSearch)
20945 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020946 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20947 split(/:|;/, $ENV{"BEINCLUDES"})
20948 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949 }
20950 if($LSearch)
20951 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20953 split(/:|;/, $ENV{"BELIBRARIES"}),
20954 split(/:|;/, $ENV{"LIBRARY_PATH"})
20955 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020956 }
20957 }
20958 if($LSearch)
20959 { # using linker to get system paths
20960 if(my $LPaths = detect_lib_default_paths())
20961 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020962 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020963 foreach my $Name (keys(%{$LPaths}))
20964 {
20965 if($SystemRoot
20966 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20967 { # wrong ldconfig configuration
20968 # check your <sysroot>/etc/ld.so.conf
20969 next;
20970 }
20971 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020972 if(my $Dir = get_dirname($LPaths->{$Name})) {
20973 $Dirs{$Dir} = 1;
20974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020975 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020976 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020977 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020978 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 }
20980 if($BSearch)
20981 {
20982 if($CrossGcc)
20983 { # --cross-gcc=arm-linux-gcc
20984 if(-e $CrossGcc)
20985 { # absolute or relative path
20986 $GCC_PATH = get_abs_path($CrossGcc);
20987 }
20988 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20989 { # command name
20990 $GCC_PATH = $CrossGcc;
20991 }
20992 else {
20993 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20994 }
20995 if($GCC_PATH=~/\s/) {
20996 $GCC_PATH = "\"".$GCC_PATH."\"";
20997 }
20998 }
20999 }
21000 if($GSearch)
21001 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021002 if(not $CrossGcc)
21003 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021004 $GCC_PATH = get_CmdPath("gcc");
21005 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021006 if(not $GCC_PATH)
21007 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021008 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021009 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021010 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021011 { # select the latest version
21012 @GCCs = sort {$b cmp $a} @GCCs;
21013 if(check_gcc($GCCs[0], "3"))
21014 {
21015 $GCC_PATH = $GCCs[0];
21016 last;
21017 }
21018 }
21019 }
21020 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021 if(not $GCC_PATH) {
21022 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21023 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021024
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021025 my $GCC_Ver = get_dumpversion($GCC_PATH);
21026 if($GCC_Ver eq "4.8")
21027 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21028 my $Info = `$GCC_PATH --version`;
21029
21030 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21031 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21032 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21033 $GCC_Ver = $2;
21034 }
21035 }
21036
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021037 if($OStarget=~/macos/)
21038 {
21039 my $Info = `$GCC_PATH --version`;
21040
21041 if($Info=~/clang/i) {
21042 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21043 }
21044 }
21045
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021046 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021047 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021048 my $GccTarget = get_dumpmachine($GCC_PATH);
21049
21050 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021051 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021052 $OStarget = "linux";
21053 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021054 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021055 elsif($GccTarget=~/symbian/)
21056 {
21057 $OStarget = "symbian";
21058 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21059 }
21060
21061 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21062
21063 # check GCC version
21064 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21065 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021066 # introduced in 4.8 and fixed in 4.8.3
21067 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update GCC to 4.8.3 or downgrade it to 4.7. You can use a local GCC installation by --gcc-path=PATH option.");
21068
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021069 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021070 }
21071 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021072 else {
21073 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074 }
21075 }
21076 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021077 {
21078 # GCC standard paths
21079 if($GCC_PATH and not $NoStdInc)
21080 {
21081 my %DPaths = detect_inc_default_paths();
21082 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21083 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21084 @DefaultIncPaths = @{$DPaths{"Inc"}};
21085 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21086 }
21087
21088 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021089 my $IncPath = "/usr/include";
21090 if($SystemRoot) {
21091 $IncPath = $SystemRoot.$IncPath;
21092 }
21093 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021094 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021095 }
21096 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021097
21098 if($ExtraInfo)
21099 {
21100 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21101 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021103}
21104
21105sub getLIB_EXT($)
21106{
21107 my $Target = $_[0];
21108 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21109 return $Ext;
21110 }
21111 return $OS_LibExt{$LIB_TYPE}{"default"};
21112}
21113
21114sub getAR_EXT($)
21115{
21116 my $Target = $_[0];
21117 if(my $Ext = $OS_Archive{$Target}) {
21118 return $Ext;
21119 }
21120 return $OS_Archive{"default"};
21121}
21122
21123sub get_dumpversion($)
21124{
21125 my $Cmd = $_[0];
21126 return "" if(not $Cmd);
21127 if($Cache{"get_dumpversion"}{$Cmd}) {
21128 return $Cache{"get_dumpversion"}{$Cmd};
21129 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021130 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021131 chomp($V);
21132 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21133}
21134
21135sub get_dumpmachine($)
21136{
21137 my $Cmd = $_[0];
21138 return "" if(not $Cmd);
21139 if($Cache{"get_dumpmachine"}{$Cmd}) {
21140 return $Cache{"get_dumpmachine"}{$Cmd};
21141 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021142 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 chomp($Machine);
21144 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21145}
21146
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021147sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021148{
21149 my $Cmd = $_[0];
21150 return "" if(not $Cmd);
21151 my @Options = (
21152 "--version",
21153 "-help"
21154 );
21155 foreach my $Opt (@Options)
21156 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021157 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021158 if($Info) {
21159 return 1;
21160 }
21161 }
21162 return 0;
21163}
21164
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021165sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021166{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021167 my ($Cmd, $ReqVer) = @_;
21168 return 0 if(not $Cmd or not $ReqVer);
21169 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21170 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021171 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021172 if(my $GccVer = get_dumpversion($Cmd))
21173 {
21174 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21175 if(cmpVersions($GccVer, $ReqVer)>=0) {
21176 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21177 }
21178 }
21179 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021180}
21181
21182sub get_depth($)
21183{
21184 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021185 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021186 }
21187 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21188}
21189
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021190sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021191{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021192 return if($Cache{"registerGccHeaders"}); # this function should be called once
21193
21194 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021195 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021196 my @Headers = cmd_find($Path,"f");
21197 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21198 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021199 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021200 my $FileName = get_filename($HPath);
21201 if(not defined $DefaultGccHeader{$FileName})
21202 { # skip duplicated
21203 $DefaultGccHeader{$FileName} = $HPath;
21204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021205 }
21206 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021207 $Cache{"registerGccHeaders"} = 1;
21208}
21209
21210sub registerCppHeaders()
21211{
21212 return if($Cache{"registerCppHeaders"}); # this function should be called once
21213
21214 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021215 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021216 my @Headers = cmd_find($CppDir,"f");
21217 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21218 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021219 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021220 my $FileName = get_filename($Path);
21221 if(not defined $DefaultCppHeader{$FileName})
21222 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021223 $DefaultCppHeader{$FileName} = $Path;
21224 }
21225 }
21226 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021227 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021228}
21229
21230sub parse_libname($$$)
21231{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021232 return "" if(not $_[0]);
21233 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21234 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021235 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021236 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21237}
21238
21239sub parse_libname_I($$$)
21240{
21241 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021243 if($Target eq "symbian") {
21244 return parse_libname_symbian($Name, $Type);
21245 }
21246 elsif($Target eq "windows") {
21247 return parse_libname_windows($Name, $Type);
21248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021249
21250 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021251 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021252 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021253 { # libSDL-1.2.so.0.7.1
21254 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021255 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021256 if($Type eq "name")
21257 { # libSDL-1.2
21258 # libwbxml2
21259 return $2;
21260 }
21261 elsif($Type eq "name+ext")
21262 { # libSDL-1.2.so
21263 # libwbxml2.so
21264 return $1;
21265 }
21266 elsif($Type eq "version")
21267 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021268 if(defined $7
21269 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021270 { # 0.7.1
21271 return $7;
21272 }
21273 else
21274 { # libc-2.5.so (=>2.5 version)
21275 my $MV = $5;
21276 $MV=~s/\A[\-\_]+//g;
21277 return $MV;
21278 }
21279 }
21280 elsif($Type eq "short")
21281 { # libSDL
21282 # libwbxml2
21283 return $3;
21284 }
21285 elsif($Type eq "shortest")
21286 { # SDL
21287 # wbxml
21288 return shortest_name($3);
21289 }
21290 }
21291 return "";# error
21292}
21293
21294sub parse_libname_symbian($$)
21295{
21296 my ($Name, $Type) = @_;
21297 my $Ext = getLIB_EXT("symbian");
21298 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21299 { # libpthread{00010001}.dso
21300 if($Type eq "name")
21301 { # libpthread{00010001}
21302 return $2;
21303 }
21304 elsif($Type eq "name+ext")
21305 { # libpthread{00010001}.dso
21306 return $1;
21307 }
21308 elsif($Type eq "version")
21309 { # 00010001
21310 my $V = $4;
21311 $V=~s/\{(.+)\}/$1/;
21312 return $V;
21313 }
21314 elsif($Type eq "short")
21315 { # libpthread
21316 return $3;
21317 }
21318 elsif($Type eq "shortest")
21319 { # pthread
21320 return shortest_name($3);
21321 }
21322 }
21323 return "";# error
21324}
21325
21326sub parse_libname_windows($$)
21327{
21328 my ($Name, $Type) = @_;
21329 my $Ext = getLIB_EXT("windows");
21330 if($Name=~/((.+?)\.$Ext)\Z/)
21331 { # netapi32.dll
21332 if($Type eq "name")
21333 { # netapi32
21334 return $2;
21335 }
21336 elsif($Type eq "name+ext")
21337 { # netapi32.dll
21338 return $1;
21339 }
21340 elsif($Type eq "version")
21341 { # DLL version embedded
21342 # at binary-level
21343 return "";
21344 }
21345 elsif($Type eq "short")
21346 { # netapi32
21347 return $2;
21348 }
21349 elsif($Type eq "shortest")
21350 { # netapi
21351 return shortest_name($2);
21352 }
21353 }
21354 return "";# error
21355}
21356
21357sub shortest_name($)
21358{
21359 my $Name = $_[0];
21360 # remove prefix
21361 $Name=~s/\A(lib|open)//;
21362 # remove suffix
21363 $Name=~s/[\W\d_]+\Z//i;
21364 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21365 return $Name;
21366}
21367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021368sub createSymbolsList($$$$$)
21369{
21370 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021372 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021373 prepareSymbols(1);
21374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021375 my %SymbolHeaderLib = ();
21376 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021378 # Get List
21379 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21380 {
21381 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021382 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021383 next;
21384 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021385 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021386 { # skip other symbols
21387 next;
21388 }
21389 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21390 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021391 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021392 next;
21393 }
21394 my $DyLib = $Symbol_Library{1}{$Symbol};
21395 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021396 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021397 next;
21398 }
21399 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21400 $Total+=1;
21401 }
21402 # Draw List
21403 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21404 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21405 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21406 {
21407 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21408 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409 my %NS_Symbol = ();
21410 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021411 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021412 }
21413 foreach my $NameSpace (sort keys(%NS_Symbol))
21414 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021415 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021416 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21417 foreach my $Symbol (@SortedInterfaces)
21418 {
21419 my $SubReport = "";
21420 my $Signature = get_Signature($Symbol, 1);
21421 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021422 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021423 }
21424 if($Symbol=~/\A(_Z|\?)/)
21425 {
21426 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021427 $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 +040021428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021429 else {
21430 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21431 }
21432 }
21433 else
21434 {
21435 if($Signature) {
21436 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21437 }
21438 else {
21439 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21440 }
21441 }
21442 $SYMBOLS_LIST .= $SubReport;
21443 }
21444 }
21445 $SYMBOLS_LIST .= "<br/>\n";
21446 }
21447 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021448 # clear info
21449 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21450 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21451 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21452 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021453 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021454 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021455 my $CssStyles = readModule("Styles", "SymbolsList.css");
21456 my $JScripts = readModule("Scripts", "Sections.js");
21457 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021458 my $Title = "$LName: public symbols";
21459 my $Keywords = "$LName, API, symbols";
21460 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021461 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021462 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021463 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021464 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021465 writeFile($SaveTo, $SYMBOLS_LIST);
21466}
21467
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021468sub add_target_libs($)
21469{
21470 foreach (@{$_[0]}) {
21471 $TargetLibs{$_} = 1;
21472 }
21473}
21474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021475sub is_target_lib($)
21476{
21477 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021478 if(not $LName) {
21479 return 0;
21480 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021481 if($TargetLibraryName
21482 and $LName!~/\Q$TargetLibraryName\E/) {
21483 return 0;
21484 }
21485 if(keys(%TargetLibs)
21486 and not $TargetLibs{$LName}
21487 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21488 return 0;
21489 }
21490 return 1;
21491}
21492
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021493sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021494{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021495 my ($H, $V) = @_;
21496 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021497 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021498 if($TargetHeaders{$V}{$H}) {
21499 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021500 }
21501 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021502 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021503}
21504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021505sub readLibs($)
21506{
21507 my $LibVersion = $_[0];
21508 if($OStarget eq "windows")
21509 { # dumpbin.exe will crash
21510 # without VS Environment
21511 check_win32_env();
21512 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021513 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021514 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021515 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021516}
21517
21518sub dump_sorting($)
21519{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021520 my $Hash = $_[0];
21521 return [] if(not $Hash);
21522 my @Keys = keys(%{$Hash});
21523 return [] if($#Keys<0);
21524 if($Keys[0]=~/\A\d+\Z/)
21525 { # numbers
21526 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021527 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021528 else
21529 { # strings
21530 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021531 }
21532}
21533
21534sub printMsg($$)
21535{
21536 my ($Type, $Msg) = @_;
21537 if($Type!~/\AINFO/) {
21538 $Msg = $Type.": ".$Msg;
21539 }
21540 if($Type!~/_C\Z/) {
21541 $Msg .= "\n";
21542 }
21543 if($Quiet)
21544 { # --quiet option
21545 appendFile($COMMON_LOG_PATH, $Msg);
21546 }
21547 else
21548 {
21549 if($Type eq "ERROR") {
21550 print STDERR $Msg;
21551 }
21552 else {
21553 print $Msg;
21554 }
21555 }
21556}
21557
21558sub exitStatus($$)
21559{
21560 my ($Code, $Msg) = @_;
21561 printMsg("ERROR", $Msg);
21562 exit($ERROR_CODE{$Code});
21563}
21564
21565sub exitReport()
21566{ # the tool has run without any errors
21567 printReport();
21568 if($COMPILE_ERRORS)
21569 { # errors in headers may add false positives/negatives
21570 exit($ERROR_CODE{"Compile_Error"});
21571 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021572 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21573 { # --binary
21574 exit($ERROR_CODE{"Incompatible"});
21575 }
21576 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21577 { # --source
21578 exit($ERROR_CODE{"Incompatible"});
21579 }
21580 elsif($RESULT{"Source"}{"Problems"}
21581 or $RESULT{"Binary"}{"Problems"})
21582 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021583 exit($ERROR_CODE{"Incompatible"});
21584 }
21585 else {
21586 exit($ERROR_CODE{"Compatible"});
21587 }
21588}
21589
21590sub readRules($)
21591{
21592 my $Kind = $_[0];
21593 if(not -f $RULES_PATH{$Kind}) {
21594 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21595 }
21596 my $Content = readFile($RULES_PATH{$Kind});
21597 while(my $Rule = parseTag(\$Content, "rule"))
21598 {
21599 my $RId = parseTag(\$Rule, "id");
21600 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21601 foreach my $Prop (@Properties) {
21602 if(my $Value = parseTag(\$Rule, lc($Prop)))
21603 {
21604 $Value=~s/\n[ ]*//;
21605 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21606 }
21607 }
21608 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21609 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21610 }
21611 else {
21612 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21613 }
21614 }
21615}
21616
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021617sub getReportPath($)
21618{
21619 my $Level = $_[0];
21620 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21621 if($Level eq "Binary")
21622 {
21623 if($BinaryReportPath)
21624 { # --bin-report-path
21625 return $BinaryReportPath;
21626 }
21627 elsif($OutputReportPath)
21628 { # --report-path
21629 return $OutputReportPath;
21630 }
21631 else
21632 { # default
21633 return $Dir."/abi_compat_report.$ReportFormat";
21634 }
21635 }
21636 elsif($Level eq "Source")
21637 {
21638 if($SourceReportPath)
21639 { # --src-report-path
21640 return $SourceReportPath;
21641 }
21642 elsif($OutputReportPath)
21643 { # --report-path
21644 return $OutputReportPath;
21645 }
21646 else
21647 { # default
21648 return $Dir."/src_compat_report.$ReportFormat";
21649 }
21650 }
21651 else
21652 {
21653 if($OutputReportPath)
21654 { # --report-path
21655 return $OutputReportPath;
21656 }
21657 else
21658 { # default
21659 return $Dir."/compat_report.$ReportFormat";
21660 }
21661 }
21662}
21663
21664sub printStatMsg($)
21665{
21666 my $Level = $_[0];
21667 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21668}
21669
21670sub listAffected($)
21671{
21672 my $Level = $_[0];
21673 my $List = "";
21674 foreach (keys(%{$TotalAffected{$Level}}))
21675 {
21676 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21677 { # skip "Low"-severity problems
21678 next;
21679 }
21680 $List .= "$_\n";
21681 }
21682 my $Dir = get_dirname(getReportPath($Level));
21683 if($Level eq "Binary") {
21684 writeFile($Dir."/abi_affected.txt", $List);
21685 }
21686 elsif($Level eq "Source") {
21687 writeFile($Dir."/src_affected.txt", $List);
21688 }
21689}
21690
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021691sub printReport()
21692{
21693 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021694 createReport();
21695 if($JoinReport or $DoubleReport)
21696 {
21697 if($RESULT{"Binary"}{"Problems"}
21698 or $RESULT{"Source"}{"Problems"}) {
21699 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021701 else {
21702 printMsg("INFO", "result: COMPATIBLE");
21703 }
21704 printStatMsg("Binary");
21705 printStatMsg("Source");
21706 if($ListAffected)
21707 { # --list-affected
21708 listAffected("Binary");
21709 listAffected("Source");
21710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021712 elsif($BinaryOnly)
21713 {
21714 if($RESULT{"Binary"}{"Problems"}) {
21715 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21716 }
21717 else {
21718 printMsg("INFO", "result: COMPATIBLE");
21719 }
21720 printStatMsg("Binary");
21721 if($ListAffected)
21722 { # --list-affected
21723 listAffected("Binary");
21724 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021726 elsif($SourceOnly)
21727 {
21728 if($RESULT{"Source"}{"Problems"}) {
21729 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21730 }
21731 else {
21732 printMsg("INFO", "result: COMPATIBLE");
21733 }
21734 printStatMsg("Source");
21735 if($ListAffected)
21736 { # --list-affected
21737 listAffected("Source");
21738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021739 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021740 if($StdOut)
21741 {
21742 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021743 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021744 printMsg("INFO", "compatibility report has been generated to stdout");
21745 }
21746 else
21747 { # default
21748 printMsg("INFO", "compatibility reports have been generated to stdout");
21749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021751 else
21752 {
21753 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021754 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021755 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21756 }
21757 elsif($DoubleReport)
21758 { # default
21759 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21760 }
21761 elsif($BinaryOnly)
21762 { # --binary
21763 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21764 }
21765 elsif($SourceOnly)
21766 { # --source
21767 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021769 }
21770}
21771
21772sub check_win32_env()
21773{
21774 if(not $ENV{"DevEnvDir"}
21775 or not $ENV{"LIB"}) {
21776 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21777 }
21778}
21779
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021780sub diffSets($$)
21781{
21782 my ($S1, $S2) = @_;
21783 my @SK1 = keys(%{$S1});
21784 my @SK2 = keys(%{$S2});
21785 if($#SK1!=$#SK2) {
21786 return 1;
21787 }
21788 foreach my $K1 (@SK1)
21789 {
21790 if(not defined $S2->{$K1}) {
21791 return 1;
21792 }
21793 }
21794 return 0;
21795}
21796
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021797sub defaultDumpPath($$)
21798{
21799 my ($N, $V) = @_;
21800 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21801}
21802
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021803sub create_ABI_Dump()
21804{
21805 if(not -e $DumpAPI) {
21806 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21807 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021808
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021809 if(isDump($DumpAPI)) {
21810 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021811 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021812 else {
21813 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021814 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021815
21816 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021817 { # set to default: N
21818 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021819 }
21820
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021821 initLogging(1);
21822 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021823
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021824 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021825 if($OutputDumpPath)
21826 { # user defined path
21827 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021828 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021829 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21830
21831 if(not $Archive and not $StdOut)
21832 { # check archive utilities
21833 if($OSgroup eq "windows")
21834 { # using zip
21835 my $ZipCmd = get_CmdPath("zip");
21836 if(not $ZipCmd) {
21837 exitStatus("Not_Found", "can't find \"zip\"");
21838 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021839 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021840 else
21841 { # using tar and gzip
21842 my $TarCmd = get_CmdPath("tar");
21843 if(not $TarCmd) {
21844 exitStatus("Not_Found", "can't find \"tar\"");
21845 }
21846 my $GzipCmd = get_CmdPath("gzip");
21847 if(not $GzipCmd) {
21848 exitStatus("Not_Found", "can't find \"gzip\"");
21849 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021850 }
21851 }
21852
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021853 if(not $Descriptor{1}{"Dump"})
21854 {
21855 if(not $CheckHeadersOnly) {
21856 readLibs(1);
21857 }
21858 if($CheckHeadersOnly) {
21859 setLanguage(1, "C++");
21860 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021861 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021862 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021863 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021864 if(not $Descriptor{1}{"Dump"})
21865 {
21866 if($Descriptor{1}{"Headers"}) {
21867 readHeaders(1);
21868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021869 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021870 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 if(not keys(%{$SymbolInfo{1}}))
21872 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021873 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021874 {
21875 if($CheckHeadersOnly) {
21876 exitStatus("Empty_Set", "the set of public symbols is empty");
21877 }
21878 else {
21879 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21880 }
21881 }
21882 }
21883 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021884 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021885 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21886 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021887 if($ExtraDump)
21888 { # add unmangled names to the ABI dump
21889 my @Names = ();
21890 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21891 {
21892 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21893 push(@Names, $MnglName);
21894 }
21895 }
21896 translateSymbols(@Names, 1);
21897 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21898 {
21899 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21900 {
21901 if(my $Unmangled = $tr_name{$MnglName})
21902 {
21903 if($MnglName ne $Unmangled) {
21904 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21905 }
21906 }
21907 }
21908 }
21909 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021910
21911 my %GccConstants = (); # built-in GCC constants
21912 foreach my $Name (keys(%{$Constants{1}}))
21913 {
21914 if(not defined $Constants{1}{$Name}{"Header"})
21915 {
21916 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21917 delete($Constants{1}{$Name});
21918 }
21919 }
21920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021921 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021922 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021923 "TypeInfo" => $TypeInfo{1},
21924 "SymbolInfo" => $SymbolInfo{1},
21925 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021926 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021927 "SymbolVersion" => $SymVer{1},
21928 "LibraryVersion" => $Descriptor{1}{"Version"},
21929 "LibraryName" => $TargetLibraryName,
21930 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021931 "SkipTypes" => $SkipTypes{1},
21932 "SkipSymbols" => $SkipSymbols{1},
21933 "SkipNameSpaces" => $SkipNameSpaces{1},
21934 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021935 "Headers" => \%HeadersInfo,
21936 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021937 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021938 "NameSpaces" => $NestedNameSpaces{1},
21939 "Target" => $OStarget,
21940 "Arch" => getArch(1),
21941 "WordSize" => $WORD_SIZE{1},
21942 "GccVersion" => get_dumpversion($GCC_PATH),
21943 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21944 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21945 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021946 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021947 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021948 }
21949 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021950 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021952 if($ExtendedCheck)
21953 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021954 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021956 if($BinaryOnly)
21957 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021958 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021959 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021960 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021961 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021962 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021963 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21964 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021965 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021966
21967 my $ABI_DUMP = "";
21968 if($UseXML)
21969 {
21970 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021971 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021972 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021973 else
21974 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021975 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021977 if($StdOut)
21978 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021979 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021980 printMsg("INFO", "ABI dump has been generated to stdout");
21981 return;
21982 }
21983 else
21984 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021985 my ($DDir, $DName) = separate_path($DumpPath);
21986 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021987 if(not $Archive) {
21988 $DPath = $DumpPath;
21989 }
21990
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021991 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021992
21993 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021994 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021995 close(DUMP);
21996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021997 if(not -s $DPath) {
21998 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21999 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022000 if($Archive) {
22001 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022002 }
22003
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022004 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022005 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022006 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022007 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022008 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022009 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022010 # 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 +040022011 }
22012}
22013
22014sub quickEmptyReports()
22015{ # Quick "empty" reports
22016 # 4 times faster than merging equal dumps
22017 # NOTE: the dump contains the "LibraryVersion" attribute
22018 # if you change the version, then your dump will be different
22019 # OVERCOME: use -v1 and v2 options for comparing dumps
22020 # and don't change version in the XML descriptor (and dumps)
22021 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22022 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22023 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022024 my $FilePath1 = $Descriptor{1}{"Path"};
22025 my $FilePath2 = $Descriptor{2}{"Path"};
22026
22027 if(not isDump_U($FilePath1)) {
22028 $FilePath1 = unpackDump($FilePath1);
22029 }
22030
22031 if(not isDump_U($FilePath2)) {
22032 $FilePath2 = unpackDump($FilePath2);
22033 }
22034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022035 if($FilePath1 and $FilePath2)
22036 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022037 my $Line = readLineNum($FilePath1, 0);
22038 if($Line=~/xml/)
22039 { # XML format
22040 # is not supported yet
22041 return;
22042 }
22043
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022044 local $/ = undef;
22045
22046 open(DUMP1, $FilePath1);
22047 my $Content1 = <DUMP1>;
22048 close(DUMP1);
22049
22050 open(DUMP2, $FilePath2);
22051 my $Content2 = <DUMP2>;
22052 close(DUMP2);
22053
22054 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022055 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022056 # clean memory
22057 undef $Content2;
22058
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022059 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022060 my $ABIdump = eval($Content1);
22061
22062 # clean memory
22063 undef $Content1;
22064
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022065 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022066 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 +040022067 }
22068 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022069 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022070 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22071 }
22072 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022073 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022074 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22075 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022076 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022077 read_Libs_DumpInfo($ABIdump, 1);
22078 read_Machine_DumpInfo($ABIdump, 1);
22079 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022080
22081 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22082 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22083
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022084 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22085 {
22086 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22087 {
22088 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22089 next;
22090 }
22091 }
22092
22093 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22094 if($Access ne "private")
22095 {
22096 $CheckedSymbols{"Binary"}{$S} = 1;
22097 $CheckedSymbols{"Source"}{$S} = 1;
22098 }
22099 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022100
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022101 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22102 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22103 exitReport();
22104 }
22105 }
22106 }
22107}
22108
22109sub initLogging($)
22110{
22111 my $LibVersion = $_[0];
22112 # create log directory
22113 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22114 if($OutputLogPath{$LibVersion})
22115 { # user-defined by -log-path option
22116 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22117 }
22118 if($LogMode ne "n") {
22119 mkpath($LOG_DIR);
22120 }
22121 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022122 if($Debug)
22123 { # debug directory
22124 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022125
22126 if(not $ExtraInfo)
22127 { # enable --extra-info
22128 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022130 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022131 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022132}
22133
22134sub writeLog($$)
22135{
22136 my ($LibVersion, $Msg) = @_;
22137 if($LogMode ne "n") {
22138 appendFile($LOG_PATH{$LibVersion}, $Msg);
22139 }
22140}
22141
22142sub resetLogging($)
22143{
22144 my $LibVersion = $_[0];
22145 if($LogMode!~/a|n/)
22146 { # remove old log
22147 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022148 if($Debug) {
22149 rmtree($DEBUG_PATH{$LibVersion});
22150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022151 }
22152}
22153
22154sub printErrorLog($)
22155{
22156 my $LibVersion = $_[0];
22157 if($LogMode ne "n") {
22158 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22159 }
22160}
22161
22162sub isDump($)
22163{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022164 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22165 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022166 return $1;
22167 }
22168 return 0;
22169}
22170
22171sub isDump_U($)
22172{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022173 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022174 return $1;
22175 }
22176 return 0;
22177}
22178
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022179sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022180{
22181 # read input XML descriptors or ABI dumps
22182 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022183 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022184 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022185 if(not -e $Descriptor{1}{"Path"}) {
22186 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022187 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022189 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022190 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022191 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022192 if(not -e $Descriptor{2}{"Path"}) {
22193 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022194 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022196 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022197 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022198 and isDump($Descriptor{2}{"Path"}))
22199 { # optimization: equal ABI dumps
22200 quickEmptyReports();
22201 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022202
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022203 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022204
22205 if(isDump($Descriptor{1}{"Path"})) {
22206 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022207 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022208 else {
22209 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22210 }
22211
22212 if(isDump($Descriptor{2}{"Path"})) {
22213 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22214 }
22215 else {
22216 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022217 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022218
22219 if(not $Descriptor{1}{"Version"})
22220 { # set to default: X
22221 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022222 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022223 }
22224
22225 if(not $Descriptor{2}{"Version"})
22226 { # set to default: Y
22227 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022228 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022229 }
22230
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022231 if(not $UsedDump{1}{"V"}) {
22232 initLogging(1);
22233 }
22234
22235 if(not $UsedDump{2}{"V"}) {
22236 initLogging(2);
22237 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022238
22239 # check input data
22240 if(not $Descriptor{1}{"Headers"}) {
22241 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022242 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022243 if(not $Descriptor{2}{"Headers"}) {
22244 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022245 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022246
22247 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022248 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022249 if(not $Descriptor{1}{"Libs"}) {
22250 exitStatus("Error", "can't find libraries info in descriptor d1");
22251 }
22252 if(not $Descriptor{2}{"Libs"}) {
22253 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022254 }
22255 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022257 if($UseDumps)
22258 { # --use-dumps
22259 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022260 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22261 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022262
22263 unlink($DumpPath1);
22264 unlink($DumpPath2);
22265
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022266 my $pid = fork();
22267 if($pid)
22268 { # dump on two CPU cores
22269 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22270 if($RelativeDirectory{1}) {
22271 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22272 }
22273 if($OutputLogPath{1}) {
22274 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22275 }
22276 if($CrossGcc) {
22277 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22278 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022279 if($Quiet)
22280 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022281 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022282 @PARAMS = (@PARAMS, "-logging-mode", "a");
22283 }
22284 elsif($LogMode and $LogMode ne "w")
22285 { # "w" is default
22286 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022287 }
22288 if($ExtendedCheck) {
22289 @PARAMS = (@PARAMS, "-extended");
22290 }
22291 if($UserLang) {
22292 @PARAMS = (@PARAMS, "-lang", $UserLang);
22293 }
22294 if($TargetVersion{1}) {
22295 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22296 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022297 if($BinaryOnly) {
22298 @PARAMS = (@PARAMS, "-binary");
22299 }
22300 if($SourceOnly) {
22301 @PARAMS = (@PARAMS, "-source");
22302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022303 if($SortDump) {
22304 @PARAMS = (@PARAMS, "-sort");
22305 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022306 if($DumpFormat and $DumpFormat ne "perl") {
22307 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22308 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022309 if($CheckHeadersOnly) {
22310 @PARAMS = (@PARAMS, "-headers-only");
22311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022312 if($Debug)
22313 {
22314 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022315 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022318 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 exit(1);
22320 }
22321 }
22322 else
22323 { # child
22324 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22325 if($RelativeDirectory{2}) {
22326 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22327 }
22328 if($OutputLogPath{2}) {
22329 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22330 }
22331 if($CrossGcc) {
22332 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22333 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022334 if($Quiet)
22335 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022336 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022337 @PARAMS = (@PARAMS, "-logging-mode", "a");
22338 }
22339 elsif($LogMode and $LogMode ne "w")
22340 { # "w" is default
22341 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022342 }
22343 if($ExtendedCheck) {
22344 @PARAMS = (@PARAMS, "-extended");
22345 }
22346 if($UserLang) {
22347 @PARAMS = (@PARAMS, "-lang", $UserLang);
22348 }
22349 if($TargetVersion{2}) {
22350 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22351 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022352 if($BinaryOnly) {
22353 @PARAMS = (@PARAMS, "-binary");
22354 }
22355 if($SourceOnly) {
22356 @PARAMS = (@PARAMS, "-source");
22357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022358 if($SortDump) {
22359 @PARAMS = (@PARAMS, "-sort");
22360 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022361 if($DumpFormat and $DumpFormat ne "perl") {
22362 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22363 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022364 if($CheckHeadersOnly) {
22365 @PARAMS = (@PARAMS, "-headers-only");
22366 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022367 if($Debug)
22368 {
22369 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022370 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022372 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022373 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022374 exit(1);
22375 }
22376 else {
22377 exit(0);
22378 }
22379 }
22380 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022381
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022382 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022383 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22384 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022385 if($TargetTitle ne $TargetLibraryName) {
22386 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022387 }
22388 if($ShowRetVal) {
22389 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22390 }
22391 if($CrossGcc) {
22392 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22393 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022394 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22395 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022396 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022397 }
22398 if($ReportFormat and $ReportFormat ne "html")
22399 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022400 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022402 if($OutputReportPath) {
22403 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22404 }
22405 if($BinaryReportPath) {
22406 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22407 }
22408 if($SourceReportPath) {
22409 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22410 }
22411 if($LoggingPath) {
22412 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22413 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022414 if($CheckHeadersOnly) {
22415 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22416 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022417 if($BinaryOnly) {
22418 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22419 }
22420 if($SourceOnly) {
22421 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22422 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022423 if($Debug)
22424 {
22425 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22426 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022427 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022428 system("perl", $0, @CMP_PARAMS);
22429 exit($?>>8);
22430 }
22431 if(not $Descriptor{1}{"Dump"}
22432 or not $Descriptor{2}{"Dump"})
22433 { # need GCC toolchain to analyze
22434 # header files and libraries
22435 detect_default_paths("inc|lib|gcc");
22436 }
22437 if(not $Descriptor{1}{"Dump"})
22438 {
22439 if(not $CheckHeadersOnly) {
22440 readLibs(1);
22441 }
22442 if($CheckHeadersOnly) {
22443 setLanguage(1, "C++");
22444 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022445 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022446 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022447 }
22448 if(not $Descriptor{2}{"Dump"})
22449 {
22450 if(not $CheckHeadersOnly) {
22451 readLibs(2);
22452 }
22453 if($CheckHeadersOnly) {
22454 setLanguage(2, "C++");
22455 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022456 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022457 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022458 }
22459 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22460 { # support for old ABI dumps
22461 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022462 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022463 {
22464 $WORD_SIZE{1} = $WORD_SIZE{2};
22465 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022467 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022468 {
22469 $WORD_SIZE{2} = $WORD_SIZE{1};
22470 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22471 }
22472 }
22473 elsif(not $WORD_SIZE{1}
22474 and not $WORD_SIZE{2})
22475 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022476 $WORD_SIZE{1} = "4";
22477 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022478 }
22479 if($Descriptor{1}{"Dump"})
22480 { # support for old ABI dumps
22481 prepareTypes(1);
22482 }
22483 if($Descriptor{2}{"Dump"})
22484 { # support for old ABI dumps
22485 prepareTypes(2);
22486 }
22487 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22488 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22489 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022490 # process input data
22491 if($Descriptor{1}{"Headers"}
22492 and not $Descriptor{1}{"Dump"}) {
22493 readHeaders(1);
22494 }
22495 if($Descriptor{2}{"Headers"}
22496 and not $Descriptor{2}{"Dump"}) {
22497 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022498 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022499
22500 # clean memory
22501 %SystemHeaders = ();
22502 %mangled_name_gcc = ();
22503
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022504 prepareSymbols(1);
22505 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022506
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022507 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022508 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022509
22510 # Virtual Tables
22511 registerVTable(1);
22512 registerVTable(2);
22513
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022514 if(not checkDump(1, "1.22")
22515 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022516 { # support for old ABI dumps
22517 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22518 {
22519 if($ClassName=~/</)
22520 { # templates
22521 if(not defined $VirtualTable{1}{$ClassName})
22522 { # synchronize
22523 delete($VirtualTable{2}{$ClassName});
22524 }
22525 }
22526 }
22527 }
22528
22529 registerOverriding(1);
22530 registerOverriding(2);
22531
22532 setVirtFuncPositions(1);
22533 setVirtFuncPositions(2);
22534
22535 # Other
22536 addParamNames(1);
22537 addParamNames(2);
22538
22539 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022540}
22541
22542sub compareAPIs($)
22543{
22544 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022545
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022546 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022547 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022548
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022549 if($Level eq "Binary") {
22550 printMsg("INFO", "comparing ABIs ...");
22551 }
22552 else {
22553 printMsg("INFO", "comparing APIs ...");
22554 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022555
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022556 if($CheckHeadersOnly
22557 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022558 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022559 detectAdded_H($Level);
22560 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022561 }
22562 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022563 { # added/removed in libs
22564 detectAdded($Level);
22565 detectRemoved($Level);
22566 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022567
22568 mergeSymbols($Level);
22569 if(keys(%{$CheckedSymbols{$Level}})) {
22570 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022571 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022572
22573 $Cache{"mergeTypes"} = (); # free memory
22574
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022575 if($CheckHeadersOnly
22576 or $Level eq "Source")
22577 { # added/removed in headers
22578 mergeHeaders($Level);
22579 }
22580 else
22581 { # added/removed in libs
22582 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022583 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022584
22585 foreach my $S (keys(%{$CompatProblems{$Level}}))
22586 {
22587 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22588 {
22589 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22590 {
22591 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22592 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22593 }
22594 }
22595 }
22596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022597}
22598
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022599sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022600{
22601 my %Opts = (
22602 "OStarget"=>$OStarget,
22603 "Debug"=>$Debug,
22604 "Quiet"=>$Quiet,
22605 "LogMode"=>$LogMode,
22606 "CheckHeadersOnly"=>$CheckHeadersOnly,
22607
22608 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022609 "GCC_PATH"=>$GCC_PATH,
22610 "TargetSysInfo"=>$TargetSysInfo,
22611 "CrossPrefix"=>$CrossPrefix,
22612 "TargetLibraryName"=>$TargetLibraryName,
22613 "CrossGcc"=>$CrossGcc,
22614 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022615 "NoStdInc"=>$NoStdInc,
22616
22617 "BinaryOnly" => $BinaryOnly,
22618 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022619 );
22620 return \%Opts;
22621}
22622
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022623sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022624{
22625 my %CODE_ERROR = reverse(%ERROR_CODE);
22626 return $CODE_ERROR{$_[0]};
22627}
22628
22629sub scenario()
22630{
22631 if($StdOut)
22632 { # enable quiet mode
22633 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022634 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022635 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022636 if(not $LogMode)
22637 { # default
22638 $LogMode = "w";
22639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022640 if($UserLang)
22641 { # --lang=C++
22642 $UserLang = uc($UserLang);
22643 $COMMON_LANGUAGE{1}=$UserLang;
22644 $COMMON_LANGUAGE{2}=$UserLang;
22645 }
22646 if($LoggingPath)
22647 {
22648 $OutputLogPath{1} = $LoggingPath;
22649 $OutputLogPath{2} = $LoggingPath;
22650 if($Quiet) {
22651 $COMMON_LOG_PATH = $LoggingPath;
22652 }
22653 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022654
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022655 if($Quick) {
22656 $ADD_TMPL_INSTANCES = 0;
22657 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022658 if($OutputDumpPath)
22659 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022660 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022661 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22662 }
22663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022664 if($BinaryOnly and $SourceOnly)
22665 { # both --binary and --source
22666 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022667 if(not $CmpSystems)
22668 {
22669 $BinaryOnly = 0;
22670 $SourceOnly = 0;
22671 }
22672
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022673 $DoubleReport = 1;
22674 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022675
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022676 if($OutputReportPath)
22677 { # --report-path
22678 $DoubleReport = 0;
22679 $JoinReport = 1;
22680 }
22681 }
22682 elsif($BinaryOnly or $SourceOnly)
22683 { # --binary or --source
22684 $DoubleReport = 0;
22685 $JoinReport = 0;
22686 }
22687 if($UseXML)
22688 { # --xml option
22689 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022690 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022691 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022692 if($ReportFormat)
22693 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022694 $ReportFormat = lc($ReportFormat);
22695 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022696 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022698 if($ReportFormat eq "htm")
22699 { # HTM == HTML
22700 $ReportFormat = "html";
22701 }
22702 elsif($ReportFormat eq "xml")
22703 { # --report-format=XML equal to --xml
22704 $UseXML = 1;
22705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022706 }
22707 else
22708 { # default: HTML
22709 $ReportFormat = "html";
22710 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022711 if($DumpFormat)
22712 { # validate
22713 $DumpFormat = lc($DumpFormat);
22714 if($DumpFormat!~/\A(xml|perl)\Z/) {
22715 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22716 }
22717 if($DumpFormat eq "xml")
22718 { # --dump-format=XML equal to --xml
22719 $UseXML = 1;
22720 }
22721 }
22722 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022723 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022724 $DumpFormat = "perl";
22725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022726 if($Quiet and $LogMode!~/a|n/)
22727 { # --quiet log
22728 if(-f $COMMON_LOG_PATH) {
22729 unlink($COMMON_LOG_PATH);
22730 }
22731 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022732 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022733 $CheckUndefined = 1;
22734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022735 if($TestTool and $UseDumps)
22736 { # --test && --use-dumps == --test-dump
22737 $TestDump = 1;
22738 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022739 if($Tolerant)
22740 { # enable all
22741 $Tolerance = 1234;
22742 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022743 if($Help)
22744 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022745 HELP_MESSAGE();
22746 exit(0);
22747 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022748 if($InfoMsg)
22749 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022750 INFO_MESSAGE();
22751 exit(0);
22752 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022753 if($ShowVersion)
22754 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022755 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 +040022756 exit(0);
22757 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022758 if($DumpVersion)
22759 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022760 printMsg("INFO", $TOOL_VERSION);
22761 exit(0);
22762 }
22763 if($ExtendedCheck) {
22764 $CheckHeadersOnly = 1;
22765 }
22766 if($SystemRoot_Opt)
22767 { # user defined root
22768 if(not -e $SystemRoot_Opt) {
22769 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22770 }
22771 $SystemRoot = $SystemRoot_Opt;
22772 $SystemRoot=~s/[\/]+\Z//g;
22773 if($SystemRoot) {
22774 $SystemRoot = get_abs_path($SystemRoot);
22775 }
22776 }
22777 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022778
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022779 if($SortDump)
22780 {
22781 $Data::Dumper::Useperl = 1;
22782 $Data::Dumper::Sortkeys = \&dump_sorting;
22783 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022785 if($TargetLibsPath)
22786 {
22787 if(not -f $TargetLibsPath) {
22788 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22789 }
22790 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22791 $TargetLibs{$Lib} = 1;
22792 }
22793 }
22794 if($TargetHeadersPath)
22795 { # --headers-list
22796 if(not -f $TargetHeadersPath) {
22797 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22798 }
22799 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22800 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022801 $TargetHeaders{1}{get_filename($Header)} = 1;
22802 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022803 }
22804 }
22805 if($TargetHeader)
22806 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022807 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22808 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022809 }
22810 if($TestTool
22811 or $TestDump)
22812 { # --test, --test-dump
22813 detect_default_paths("bin|gcc"); # to compile libs
22814 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022815 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022816 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022817 exit(0);
22818 }
22819 if($DumpSystem)
22820 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022821
22822 if(not $TargetSysInfo) {
22823 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22824 }
22825
22826 if(not -d $TargetSysInfo) {
22827 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22828 }
22829
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022830 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022831 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022832 { # system XML descriptor
22833 if(not -f $DumpSystem) {
22834 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22835 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022836
22837 my $SDesc = readFile($DumpSystem);
22838 if(my $RelDir = $RelativeDirectory{1}) {
22839 $SDesc =~ s/{RELPATH}/$RelDir/g;
22840 }
22841
22842 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022843 foreach (@{$Ret->{"Tools"}})
22844 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022845 push_U($SystemPaths{"bin"}, $_);
22846 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022847 }
22848 if($Ret->{"CrossPrefix"}) {
22849 $CrossPrefix = $Ret->{"CrossPrefix"};
22850 }
22851 }
22852 elsif($SystemRoot_Opt)
22853 { # -sysroot "/" option
22854 # default target: /usr/lib, /usr/include
22855 # search libs: /usr/lib and /lib
22856 if(not -e $SystemRoot."/usr/lib") {
22857 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22858 }
22859 if(not -e $SystemRoot."/lib") {
22860 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22861 }
22862 if(not -e $SystemRoot."/usr/include") {
22863 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22864 }
22865 readSystemDescriptor("
22866 <name>
22867 $DumpSystem
22868 </name>
22869 <headers>
22870 $SystemRoot/usr/include
22871 </headers>
22872 <libs>
22873 $SystemRoot/usr/lib
22874 </libs>
22875 <search_libs>
22876 $SystemRoot/lib
22877 </search_libs>");
22878 }
22879 else {
22880 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22881 }
22882 detect_default_paths("bin|gcc"); # to check symbols
22883 if($OStarget eq "windows")
22884 { # to run dumpbin.exe
22885 # and undname.exe
22886 check_win32_env();
22887 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022888 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022889 exit(0);
22890 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022891
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022892 if($CmpSystems)
22893 { # --cmp-systems
22894 detect_default_paths("bin"); # to extract dumps
22895 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022896 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022897 exit(0);
22898 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022899
22900 if(not $CountSymbols)
22901 {
22902 if(not $TargetLibraryName) {
22903 exitStatus("Error", "library name is not selected (-l option)");
22904 }
22905 else
22906 { # validate library name
22907 if($TargetLibraryName=~/[\*\/\\]/) {
22908 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022910 }
22911 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022912
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022913 if(not $TargetTitle) {
22914 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022915 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022916
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022917 if($SymbolsListPath)
22918 {
22919 if(not -f $SymbolsListPath) {
22920 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22921 }
22922 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22923 $SymbolsList{$Interface} = 1;
22924 }
22925 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022926 if($TypesListPath)
22927 {
22928 if(not -f $TypesListPath) {
22929 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22930 }
22931 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22932 $TypesList{$Type} = 1;
22933 }
22934 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022935 if($SkipSymbolsListPath)
22936 {
22937 if(not -f $SkipSymbolsListPath) {
22938 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22939 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022940 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22941 {
22942 $SkipSymbols{1}{$Interface} = 1;
22943 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022944 }
22945 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022946 if($SkipTypesListPath)
22947 {
22948 if(not -f $SkipTypesListPath) {
22949 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22950 }
22951 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22952 {
22953 $SkipTypes{1}{$Type} = 1;
22954 $SkipTypes{2}{$Type} = 1;
22955 }
22956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022957 if($SkipHeadersPath)
22958 {
22959 if(not -f $SkipHeadersPath) {
22960 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22961 }
22962 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022963 { # register for both versions
22964 $SkipHeadersList{1}{$Path} = 1;
22965 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030022966
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022967 my ($CPath, $Type) = classifyPath($Path);
22968 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022969 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022970 }
22971 }
22972 if($ParamNamesPath)
22973 {
22974 if(not -f $ParamNamesPath) {
22975 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22976 }
22977 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22978 {
22979 if($Line=~s/\A(\w+)\;//)
22980 {
22981 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022982 if($Line=~/;(\d+);/)
22983 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022984 while($Line=~s/(\d+);(\w+)//) {
22985 $AddIntParams{$Interface}{$1}=$2;
22986 }
22987 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022988 else
22989 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022990 my $Num = 0;
22991 foreach my $Name (split(/;/, $Line)) {
22992 $AddIntParams{$Interface}{$Num++}=$Name;
22993 }
22994 }
22995 }
22996 }
22997 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022999 if($AppPath)
23000 {
23001 if(not -f $AppPath) {
23002 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23003 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023004
23005 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023006 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023007 $SymbolsList_App{$Interface} = 1;
23008 }
23009 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023010
23011 if($CountSymbols)
23012 {
23013 if(not -e $CountSymbols) {
23014 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23015 }
23016
23017 read_ABI_Dump(1, $CountSymbols);
23018
23019 foreach my $Id (keys(%{$SymbolInfo{1}}))
23020 {
23021 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23022 if(not $MnglName) {
23023 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23024 }
23025
23026 if(my $SV = $SymVer{1}{$MnglName}) {
23027 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23028 }
23029 else {
23030 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23031 }
23032
23033 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23034 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23035 }
23036 }
23037
23038 my $Count = 0;
23039 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23040 {
23041 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23042 next;
23043 }
23044 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23045 next;
23046 }
23047 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23048 next;
23049 }
23050
23051 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23052 }
23053
23054 printMsg("INFO", $Count);
23055 exit(0);
23056 }
23057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023058 if($DumpAPI)
23059 { # --dump-abi
23060 # make an API dump
23061 create_ABI_Dump();
23062 exit($COMPILE_ERRORS);
23063 }
23064 # default: compare APIs
23065 # -d1 <path>
23066 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023067 compareInit();
23068 if($JoinReport or $DoubleReport)
23069 {
23070 compareAPIs("Binary");
23071 compareAPIs("Source");
23072 }
23073 elsif($BinaryOnly) {
23074 compareAPIs("Binary");
23075 }
23076 elsif($SourceOnly) {
23077 compareAPIs("Source");
23078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023079 exitReport();
23080}
23081
23082scenario();