blob: c21c9592274328e775120caea95487f8bb4216af [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 $Path=~s/\\/\\\\/g;
1775 return ($Path, "Pattern");
1776 }
1777 elsif($Path=~/[\/\\]/)
1778 { # directory or relative path
1779 return (path_format($Path, $OSgroup), "Path");
1780 }
1781 else {
1782 return ($Path, "Name");
1783 }
1784}
1785
1786sub readDescriptor($$)
1787{
1788 my ($LibVersion, $Content) = @_;
1789 return if(not $LibVersion);
1790 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1791 if(not $Content) {
1792 exitStatus("Error", "$DName is empty");
1793 }
1794 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001795 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001796 }
1797 $Content=~s/\/\*(.|\n)+?\*\///g;
1798 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001799
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001800 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1801 if($TargetVersion{$LibVersion}) {
1802 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1803 }
1804 if(not $Descriptor{$LibVersion}{"Version"}) {
1805 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1806 }
1807 if($Content=~/{RELPATH}/)
1808 {
1809 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1810 $Content =~ s/{RELPATH}/$RelDir/g;
1811 }
1812 else
1813 {
1814 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1815 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1816 }
1817 }
1818
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001819 my $DHeaders = parseTag(\$Content, "headers");
1820 if(not $DHeaders) {
1821 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1822 }
1823 elsif(lc($DHeaders) ne "none")
1824 { # append the descriptor headers list
1825 if($Descriptor{$LibVersion}{"Headers"})
1826 { # multiple descriptors
1827 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001828 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001829 else {
1830 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1831 }
1832 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1833 {
1834 if(not -e $Path) {
1835 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001836 }
1837 }
1838 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001839
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001840 if(not $CheckHeadersOnly_Opt)
1841 {
1842 my $DObjects = parseTag(\$Content, "libs");
1843 if(not $DObjects) {
1844 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1845 }
1846 elsif(lc($DObjects) ne "none")
1847 { # append the descriptor libraries list
1848 if($Descriptor{$LibVersion}{"Libs"})
1849 { # multiple descriptors
1850 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1851 }
1852 else {
1853 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1854 }
1855 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1856 {
1857 if(not -e $Path) {
1858 exitStatus("Access_Error", "can't access \'$Path\'");
1859 }
1860 }
1861 }
1862 }
1863 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1864 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001865 if(not -d $Path) {
1866 exitStatus("Access_Error", "can't access directory \'$Path\'");
1867 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001868 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001870 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 }
1872 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1873 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001874 if(not -d $Path) {
1875 exitStatus("Access_Error", "can't access directory \'$Path\'");
1876 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001877 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001878 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001879 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001880 }
1881 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1882 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 if(not -d $Path) {
1884 exitStatus("Access_Error", "can't access directory \'$Path\'");
1885 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001886 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001888 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 $TargetTools{$Path}=1;
1890 }
1891 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1892 $CrossPrefix = $Prefix;
1893 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001894 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001895 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1896 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 if(not -d $Path) {
1898 exitStatus("Access_Error", "can't access directory \'$Path\'");
1899 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001900 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001901 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001902 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001904 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1906 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001907 if(not -d $Path) {
1908 exitStatus("Access_Error", "can't access directory \'$Path\'");
1909 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001910 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001912 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001913 }
1914 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001915 { # skip some auto-generated include paths
1916 if(not is_abs($Path))
1917 {
1918 if(my $P = abs_path($Path)) {
1919 $Path = $P;
1920 }
1921 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001922 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001923 }
1924 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001925 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 my ($CPath, $Type) = classifyPath($Path);
1927 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001928 }
1929 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001930 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1931 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001932 if($Option!~/\A\-(Wl|l|L)/)
1933 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001934 $CompilerOptions{$LibVersion} .= " ".$Option;
1935 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001936 }
1937 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1938 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1939 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001940 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001941
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001942 my ($CPath, $Type) = classifyPath($Path);
1943 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001944 }
1945 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1946 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1947 {
1948 my ($CPath, $Type) = classifyPath($Path);
1949 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1950 }
1951 if(my $DDefines = parseTag(\$Content, "defines"))
1952 {
1953 if($Descriptor{$LibVersion}{"Defines"})
1954 { # multiple descriptors
1955 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1956 }
1957 else {
1958 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1959 }
1960 }
1961 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1962 {
1963 if($Order=~/\A(.+):(.+)\Z/) {
1964 $Include_Order{$LibVersion}{$1} = $2;
1965 }
1966 }
1967 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1968 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001969 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001970 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1971 }
1972 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1973 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001974 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001975 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1976 }
1977 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1978 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1979 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001980 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1981 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001983 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1984 $SkipConstants{$LibVersion}{$Constant} = 1;
1985 }
1986 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1987 {
1988 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001989 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001990 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1991 }
1992 else {
1993 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1994 }
1995 }
1996}
1997
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001998sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001999{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002000 my $CodeRef = shift(@_);
2001 my $Tag = shift(@_);
2002 if(not $Tag or not $CodeRef) {
2003 return undef;
2004 }
2005 my $Sp = 0;
2006 if(@_) {
2007 $Sp = shift(@_);
2008 }
2009 my $Start = index(${$CodeRef}, "<$Tag>");
2010 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002011 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002012 my $End = index(${$CodeRef}, "</$Tag>");
2013 if($End!=-1)
2014 {
2015 my $TS = length($Tag)+3;
2016 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2017 substr($Content, 0, $TS-1, ""); # cut start tag
2018 substr($Content, -$TS, $TS, ""); # cut end tag
2019 if(not $Sp)
2020 {
2021 $Content=~s/\A\s+//g;
2022 $Content=~s/\s+\Z//g;
2023 }
2024 if(substr($Content, 0, 1) ne "<") {
2025 $Content = xmlSpecChars_R($Content);
2026 }
2027 return $Content;
2028 }
2029 }
2030 return undef;
2031}
2032
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002033sub getInfo($)
2034{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002035 my $DumpPath = $_[0];
2036 return if(not $DumpPath or not -f $DumpPath);
2037
2038 readTUDump($DumpPath);
2039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002040 # processing info
2041 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002042
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002043 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002044 setAnonTypedef_All();
2045 }
2046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002047 getTypeInfo_All();
2048 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002049 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002051 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002053 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002054 %LibInfo = ();
2055 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002056 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002057 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002058 %TemplateDecl = ();
2059 %StdCxxTypedef = ();
2060 %MissedTypedef = ();
2061 %Typedef_Tr = ();
2062 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002063 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002064
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002065 # clean cache
2066 delete($Cache{"getTypeAttr"});
2067 delete($Cache{"getTypeDeclId"});
2068
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002069 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002070 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002071 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002072 }
2073 else
2074 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002075 if($BinaryOnly and not $ExtendedCheck)
2076 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002077 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002078 }
2079 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002080 remove_Unused($Version, "Extended");
2081 }
2082 }
2083
2084 if($CheckInfo)
2085 {
2086 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2087 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2088 }
2089
2090 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2091 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002093 }
2094
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002095 if($Debug) {
2096 # debugMangling($Version);
2097 }
2098}
2099
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002100sub readTUDump($)
2101{
2102 my $DumpPath = $_[0];
2103
2104 open(TU_DUMP, $DumpPath);
2105 local $/ = undef;
2106 my $Content = <TU_DUMP>;
2107 close(TU_DUMP);
2108
2109 unlink($DumpPath);
2110
2111 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002112 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113
2114 # clean memory
2115 undef $Content;
2116
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002117 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002118
2119 foreach (0 .. $#Lines)
2120 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002121 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002122 { # get a number and attributes of a node
2123 next if(not $NodeType{$2});
2124 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002125 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002126 }
2127
2128 # clean memory
2129 delete($Lines[$_]);
2130 }
2131
2132 # clean memory
2133 undef @Lines;
2134}
2135
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002136sub simplifyConstants()
2137{
2138 foreach my $Constant (keys(%{$Constants{$Version}}))
2139 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002140 if(defined $Constants{$Version}{$Constant}{"Header"})
2141 {
2142 my $Value = $Constants{$Version}{$Constant}{"Value"};
2143 if(defined $EnumConstants{$Version}{$Value}) {
2144 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2145 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002146 }
2147 }
2148}
2149
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002150sub simplifyNames()
2151{
2152 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2153 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002154 if($Typedef_Eq{$Version}{$Base}) {
2155 next;
2156 }
2157 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2158 if($#Translations==0)
2159 {
2160 if(length($Translations[0])<=length($Base)) {
2161 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2162 }
2163 }
2164 else
2165 { # select most appropriate
2166 foreach my $Tr (@Translations)
2167 {
2168 if($Base=~/\A\Q$Tr\E/)
2169 {
2170 $Typedef_Eq{$Version}{$Base} = $Tr;
2171 last;
2172 }
2173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002174 }
2175 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002176 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002177 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002178 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002179 if(not $TypeName) {
2180 next;
2181 }
2182 next if(index($TypeName,"<")==-1);# template instances only
2183 if($TypeName=~/>(::\w+)+\Z/)
2184 { # skip unused types
2185 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002186 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002187 foreach my $Base (sort {length($b)<=>length($a)}
2188 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002189 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002190 next if(not $Base);
2191 next if(index($TypeName,$Base)==-1);
2192 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002193 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002194 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002195 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2196 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2197 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002198 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002199 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2200 {
2201 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2202 {
2203 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2204 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002205 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002206 }
2207 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002208 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002210 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002211 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002212 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2213 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002214 }
2215}
2216
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002217sub setAnonTypedef_All()
2218{
2219 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2220 {
2221 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2222 {
2223 if(isAnon(getNameByInfo($InfoId))) {
2224 $TypedefToAnon{getTypeId($InfoId)} = 1;
2225 }
2226 }
2227 }
2228}
2229
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002230sub setTemplateParams_All()
2231{
2232 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2233 {
2234 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2235 setTemplateParams($_);
2236 }
2237 }
2238}
2239
2240sub setTemplateParams($)
2241{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002242 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002243 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002244 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002245 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002246 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002247 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002248 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002249 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002250 setTemplateInstParams($_[0], $TmplInst_Id);
2251 }
2252 }
2253
2254 $BasicTemplate{$Version}{$Tid} = $_[0];
2255
2256 if(my $Prms = getTreeAttr_Prms($_[0]))
2257 {
2258 if(my $Valu = getTreeAttr_Valu($Prms))
2259 {
2260 my $Vector = getTreeVec($Valu);
2261 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2262 {
2263 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2264 {
2265 if(my $Name = getNameByInfo($Val))
2266 {
2267 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2268 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2269 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2270 }
2271 else {
2272 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2273 }
2274 }
2275 }
2276 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002278 }
2279 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002280 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002281 {
2282 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2283 {
2284 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002285 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002286 }
2287 }
2288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002289}
2290
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002291sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002292{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002293 my ($Tmpl, $Inst) = @_;
2294
2295 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002296 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002297 my ($Params_InfoId, $ElemId) = ();
2298 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2299 $Params_InfoId = $1;
2300 }
2301 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2302 $ElemId = $1;
2303 }
2304 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002305 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002306 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2307 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2308 {
2309 my ($PPos, $PTypeId) = ($1, $2);
2310 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2311 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002312 if($PType eq "template_type_parm") {
2313 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002314 }
2315 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002316 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2317 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002318 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002319 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002320 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002321 else
2322 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002323 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002324 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002325 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002326 }
2327 }
2328 }
2329}
2330
2331sub getTypeDeclId($)
2332{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002333 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002334 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002335 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2336 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2337 }
2338 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2339 {
2340 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2341 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2342 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002344 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002345 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002346}
2347
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002348sub getTypeInfo_All()
2349{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002350 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002351 { # support for GCC < 4.5
2352 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2353 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2354 # FIXME: check GCC versions
2355 addMissedTypes_Pre();
2356 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002357
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002358 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002359 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002360 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2361 if($IType=~/_type\Z/ and $IType ne "function_type"
2362 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002363 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002364 }
2365 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002366
2367 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002368 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002369 "Name" => "...",
2370 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002371 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002373 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002374
2375 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002376 { # support for GCC < 4.5
2377 addMissedTypes_Post();
2378 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002379
2380 if($ADD_TMPL_INSTANCES)
2381 {
2382 # templates
2383 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2384 {
2385 if(defined $TemplateMap{$Version}{$Tid}
2386 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2387 {
2388 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2389 {
2390 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2391 {
2392 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2393 {
2394 if(my %MAttr = getTypeAttr($MembTypeId))
2395 {
2396 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2397 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2398 }
2399 }
2400 }
2401 }
2402 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2403 {
2404 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2405 {
2406 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2407
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002408 if($NBid ne $Bid
2409 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002410 {
2411 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2412 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2413 }
2414 }
2415 }
2416 }
2417 }
2418 }
2419}
2420
2421sub createType($$)
2422{
2423 my ($Attr, $LibVersion) = @_;
2424 my $NewId = ++$MAX_ID;
2425
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002426 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002427 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002428 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002429
2430 return "$NewId";
2431}
2432
2433sub instType($$$)
2434{ # create template instances
2435 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002436
2437 if(not $TypeInfo{$LibVersion}{$Tid}) {
2438 return undef;
2439 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002440 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2441
2442 foreach my $Key (sort keys(%{$Map}))
2443 {
2444 if(my $Val = $Map->{$Key})
2445 {
2446 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2447
2448 if(defined $Attr->{"NameSpace"}) {
2449 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2450 }
2451 foreach (keys(%{$Attr->{"TParam"}})) {
2452 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2453 }
2454 }
2455 else
2456 { # remove absent
2457 # _Traits, etc.
2458 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002459 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002460 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2461 }
2462 foreach (keys(%{$Attr->{"TParam"}}))
2463 {
2464 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2465 delete($Attr->{"TParam"}{$_});
2466 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002467 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002468 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2469 }
2470 }
2471 }
2472 }
2473
2474 my $Tmpl = 0;
2475
2476 if(defined $Attr->{"TParam"})
2477 {
2478 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2479 {
2480 my $PName = $Attr->{"TParam"}{$_}{"name"};
2481
2482 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2483 {
2484 my %Base = get_BaseType($PTid, $LibVersion);
2485
2486 if($Base{"Type"} eq "TemplateParam"
2487 or defined $Base{"Template"})
2488 {
2489 $Tmpl = 1;
2490 last
2491 }
2492 }
2493 }
2494 }
2495
2496 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2497 return "$Id";
2498 }
2499 else
2500 {
2501 if(not $Tmpl) {
2502 delete($Attr->{"Template"});
2503 }
2504
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002505 my $New = createType($Attr, $LibVersion);
2506
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002507 my %EMap = ();
2508 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2509 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2510 }
2511 foreach (keys(%{$Map})) {
2512 $EMap{$_} = $Map->{$_};
2513 }
2514
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002515 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2516 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002517 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002518 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002519 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002520 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002521 {
2522 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2523
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002524 if($NBid ne $Bid
2525 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002526 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002527 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2528 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 }
2530 }
2531 }
2532
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002533 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002534 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002535 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2536 {
2537 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2538 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2539 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002540 }
2541 }
2542
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002543 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002544 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002545 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2546 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002547 }
2548 }
2549
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002550 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2551 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002552 }
2553
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002554 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002556}
2557
2558sub addMissedTypes_Pre()
2559{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002560 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002561 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2562 { # detecting missed typedefs
2563 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2564 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002565 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002566 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002567 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002568 if($TypeType eq "Unknown")
2569 { # template_type_parm
2570 next;
2571 }
2572 my $TypeDeclId = getTypeDeclId($TypeId);
2573 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2574 my $TypedefName = getNameByInfo($MissedTDid);
2575 next if(not $TypedefName);
2576 next if($TypedefName eq "__float80");
2577 next if(isAnon($TypedefName));
2578 if(not $TypeDeclId
2579 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002580 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 }
2582 }
2583 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002584 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002585 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002586 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002587 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002589 next;
2590 }
2591 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002593 if(not $TypedefName) {
2594 next;
2595 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002596 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002597 my %MissedInfo = ( # typedef info
2598 "Name" => $TypedefName,
2599 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002600 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002601 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002602 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 my ($H, $L) = getLocation($MissedTDid);
2604 $MissedInfo{"Header"} = $H;
2605 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002606 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002607 { # other types
2608 next;
2609 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002610 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 next;
2613 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002614 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002616 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002618 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002619 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 next;
2621 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002622 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002623 next;
2624 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002625 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002627 next;
2628 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002629 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002631 next;
2632 }
2633 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002634
2635 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002638 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002639 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002640 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002642
2643 # add missed & remove other
2644 $TypeInfo{$Version} = \%AddTypes;
2645 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002646}
2647
2648sub addMissedTypes_Post()
2649{
2650 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2651 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002652 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2653 {
2654 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2655 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2656 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2657 }
2658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002659 }
2660}
2661
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002662sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002663{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002664 my $TypeId = $_[0];
2665 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2666 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002667 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002668 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002670}
2671
2672sub getArraySize($$)
2673{
2674 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002675 if(my $Size = getSize($TypeId))
2676 {
2677 my $Elems = $Size/$BYTE_SIZE;
2678 while($BaseName=~s/\s*\[(\d+)\]//) {
2679 $Elems/=$1;
2680 }
2681 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2682 {
2683 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2684 $Elems/=$BasicSize;
2685 }
2686 }
2687 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002688 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002689 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690}
2691
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002692sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002693{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002694 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002695 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002696 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2697 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002699 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2700 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2701 if(not $NodeType)
2702 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002703 return ();
2704 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002705 if($NodeType eq "tree_vec")
2706 {
2707 if($Pos!=$#Positions)
2708 { # select last vector of parameters ( ns<P1>::type<P2> )
2709 next;
2710 }
2711 }
2712 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2713 foreach my $P (@Params)
2714 {
2715 if($P eq "") {
2716 return ();
2717 }
2718 elsif($P ne "\@skip\@") {
2719 @TmplParams = (@TmplParams, $P);
2720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002721 }
2722 }
2723 return @TmplParams;
2724}
2725
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002726sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002727{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002729 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002730 if(defined $TypeInfo{$Version}{$TypeId}
2731 and $TypeInfo{$Version}{$TypeId}{"Name"})
2732 { # already created
2733 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002735 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2736 { # incomplete type
2737 return ();
2738 }
2739 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2740
2741 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743
2744 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2745 {
2746 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2747 {
2748 if($Info=~/qual[ ]*:/)
2749 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002750 my $NewId = ++$MAX_ID;
2751
2752 $MissedBase{$Version}{$TypeId} = "$NewId";
2753 $MissedBase_R{$Version}{$NewId} = $TypeId;
2754 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2755 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002756 }
2757 }
2758 $TypeAttr{"Type"} = "Typedef";
2759 }
2760 else {
2761 $TypeAttr{"Type"} = getTypeType($TypeId);
2762 }
2763
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002764 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2765 {
2766 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2767 { # local code
2768 return ();
2769 }
2770 }
2771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002772 if($TypeAttr{"Type"} eq "Unknown") {
2773 return ();
2774 }
2775 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2776 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002777 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002778 if(my $TName = $TypeAttr{"Name"})
2779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002780 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002781 $TName_Tid{$Version}{$TName} = $TypeId;
2782 return %TypeAttr;
2783 }
2784 else {
2785 return ();
2786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002787 }
2788 elsif($TypeAttr{"Type"} eq "Array")
2789 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002790 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2791 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002792 return ();
2793 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002794 if(my $Algn = getAlgn($TypeId)) {
2795 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2796 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002797 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002798 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002799 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002800 if(not $BTAttr{"Name"}) {
2801 return ();
2802 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002803 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002804 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002805 if(my $Size = getSize($TypeId)) {
2806 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2807 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002808 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002809 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2810 }
2811 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002812 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002814 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002815 else
2816 {
2817 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002818 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002819 $TypeAttr{"Name"} = $1."[]".$2;
2820 }
2821 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002822 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002824 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002825 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002826 if($BTAttr{"Header"}) {
2827 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002828 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002830 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2831 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002832 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002833 return ();
2834 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002835 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002836 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002837 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002838 if($TypeAttr{"Name"})
2839 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002840 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002841
2842 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2843 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002844 { # NOTE: register only one int: with built-in decl
2845 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2846 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2847 }
2848 }
2849 return %TypeAttr;
2850 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002851 else {
2852 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002854 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002855 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2856 {
2857 %TypeAttr = getTrivialTypeAttr($TypeId);
2858 if($TypeAttr{"Name"})
2859 {
2860 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2861 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2862 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2863 }
2864 return %TypeAttr;
2865 }
2866 else {
2867 return ();
2868 }
2869 }
2870 elsif($TypeAttr{"Type"} eq "SizeOf")
2871 {
2872 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2873 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2874 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2875 if($TypeAttr{"Name"})
2876 {
2877 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2878 return %TypeAttr;
2879 }
2880 else {
2881 return ();
2882 }
2883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002884 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002885 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2887 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002888 return ();
2889 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002890 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002891 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002892 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002893 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002894 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002895 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002896 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002898 }
2899 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002900 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002901 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002902 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002903 return ();
2904 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002905 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002907 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002908 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002909 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002910 }
2911 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002912 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002913 {
2914 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002915 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002916 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002917 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002918 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2919 }
2920 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002921 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002922 }
2923 }
2924 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002925 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002926 }
2927 if($TypeAttr{"Type"} eq "Typedef")
2928 {
2929 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002930
2931 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2932 return ();
2933 }
2934
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002935 if(isAnon($TypeAttr{"Name"}))
2936 { # anon typedef to anon type: ._N
2937 return ();
2938 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002939
2940 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2941 { # artificial typedef of "struct X" to "X"
2942 $TypeAttr{"Artificial"} = 1;
2943 }
2944
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002945 if(my $NS = getNameSpace($TypeDeclId))
2946 {
2947 my $TypeName = $TypeAttr{"Name"};
2948 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2949 { # "some_type" is the typedef to "struct some_type" in C++
2950 if($3) {
2951 $TypeAttr{"Name"} = $3."::".$TypeName;
2952 }
2953 }
2954 else
2955 {
2956 $TypeAttr{"NameSpace"} = $NS;
2957 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002958
2959 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2960 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2961 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 if($BTAttr{"NameSpace"}
2963 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002964 { # types like "std::fpos<__mbstate_t>" are
2965 # not covered by typedefs in the TU dump
2966 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002967 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2968 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002969 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002971 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002972 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002974 }
2975 }
2976 }
2977 }
2978 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002979 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002980 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002981 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002982 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2983 { # typedef int*const TYPEDEF; // first
2984 # int foo(TYPEDEF p); // const is optimized out
2985 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2986 if($BTAttr{"Name"}=~/</)
2987 {
2988 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2989 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002991 }
2992 }
2993 }
2994 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2995 }
2996 if(not $TypeAttr{"Size"})
2997 {
2998 if($TypeAttr{"Type"} eq "Pointer") {
2999 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3000 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003001 elsif($BTAttr{"Size"}) {
3002 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003003 }
3004 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003005 if(my $Algn = getAlgn($TypeId)) {
3006 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3007 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003008 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003009 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3010 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003011 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003012 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003013 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003014 { # typedef to "class Class"
3015 # should not be registered in TName_Tid
3016 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3017 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3018 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003019 }
3020 return %TypeAttr;
3021 }
3022}
3023
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003024sub getTreeVec($)
3025{
3026 my %Vector = ();
3027 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3028 {
3029 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3030 { # string length is N-1 because of the null terminator
3031 $Vector{$1} = $2;
3032 }
3033 }
3034 return \%Vector;
3035}
3036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003037sub get_TemplateParam($$)
3038{
3039 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003040 return () if(not $Type_Id);
3041 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3042 return () if(not $NodeType);
3043 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003044 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003045 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003046 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 my $Num = getNodeIntCst($Type_Id);
3048 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003049 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 }
3051 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003052 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003053 }
3054 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003055 elsif($NodeType eq "string_cst") {
3056 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003057 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003058 elsif($NodeType eq "tree_vec")
3059 {
3060 my $Vector = getTreeVec($Type_Id);
3061 my @Params = ();
3062 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3063 {
3064 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3065 push(@Params, $P2);
3066 }
3067 }
3068 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003070 elsif($NodeType eq "parm_decl")
3071 {
3072 (getNameByInfo($Type_Id));
3073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 else
3075 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003076 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003077 my $PName = $ParamAttr{"Name"};
3078 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003079 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003080 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003081 if($PName=~/\>/)
3082 {
3083 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003084 $PName = $Cover;
3085 }
3086 }
3087 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003088 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003089 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3090 # template<typename _Key, typename _Compare = std::less<_Key>
3091 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3092 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3093 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3094 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003095 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003097 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003098 }
3099}
3100
3101sub cover_stdcxx_typedef($)
3102{
3103 my $TypeName = $_[0];
3104 if(my @Covers = sort {length($a)<=>length($b)}
3105 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3106 { # take the shortest typedef
3107 # FIXME: there may be more than
3108 # one typedefs to the same type
3109 return $Covers[0];
3110 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003111 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003112 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3113 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3114 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003115 if(my $Cover = $Covers[0])
3116 {
3117 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3118 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003120 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003121 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003122}
3123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003124sub getNodeIntCst($)
3125{
3126 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003127 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003128 if($EnumMembName_Id{$Version}{$CstId}) {
3129 return $EnumMembName_Id{$Version}{$CstId};
3130 }
3131 elsif((my $Value = getTreeValue($CstId)) ne "")
3132 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003133 if($Value eq "0")
3134 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003135 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136 return "false";
3137 }
3138 else {
3139 return "0";
3140 }
3141 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003142 elsif($Value eq "1")
3143 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003144 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003145 return "true";
3146 }
3147 else {
3148 return "1";
3149 }
3150 }
3151 else {
3152 return $Value;
3153 }
3154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003155 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156}
3157
3158sub getNodeStrCst($)
3159{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003160 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3161 {
3162 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003163 {
3164 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3165 { # string length is N-1 because of the null terminator
3166 return substr($1, 0, $2-1);
3167 }
3168 else
3169 { # identifier_node
3170 return substr($1, 0, $2);
3171 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003174 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003175}
3176
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003177sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003179 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003180 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3181 if($Type eq "FieldPtr") {
3182 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3183 }
3184 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3185 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003186 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003187 if($Type eq "MethodPtr")
3188 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003189 if(my $Size = getSize($TypeId))
3190 {
3191 $Size/=$BYTE_SIZE;
3192 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003194 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003195 if(my $Algn = getAlgn($TypeId)) {
3196 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198 # Return
3199 if($Type eq "FieldPtr")
3200 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003202 if($ReturnAttr{"Name"}) {
3203 $MemPtrName .= $ReturnAttr{"Name"};
3204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205 $TypeAttr{"Return"} = $PtrId;
3206 }
3207 else
3208 {
3209 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3210 {
3211 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003212 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3213 if(not $ReturnAttr{"Name"})
3214 { # templates
3215 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003216 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003217 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003218 $TypeAttr{"Return"} = $ReturnTypeId;
3219 }
3220 }
3221 # Class
3222 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3223 {
3224 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003225 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 if($Class{"Name"}) {
3227 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3228 }
3229 else {
3230 $MemPtrName .= " (*)";
3231 }
3232 }
3233 else {
3234 $MemPtrName .= " (*)";
3235 }
3236 # Parameters
3237 if($Type eq "FuncPtr"
3238 or $Type eq "MethodPtr")
3239 {
3240 my @ParamTypeName = ();
3241 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3242 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003243 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003244 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003245 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003246 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003247 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3248 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003250 my $PTypeId = $1;
3251 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003252 if(not $ParamAttr{"Name"})
3253 { # templates (template_type_parm), etc.
3254 return ();
3255 }
3256 if($ParamAttr{"Name"} eq "void") {
3257 last;
3258 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003259 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003260 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003261 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003262 push(@ParamTypeName, $ParamAttr{"Name"});
3263 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003264 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3265 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003266 }
3267 else {
3268 last;
3269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003270 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003271 else {
3272 last;
3273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 }
3275 }
3276 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3277 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003278 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003279 return %TypeAttr;
3280}
3281
3282sub getTreeTypeName($)
3283{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003284 my $TypeId = $_[0];
3285 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003286 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003287 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003289 if(my $Name = getNameByInfo($TypeId))
3290 { # bit_size_type
3291 return $Name;
3292 }
3293 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294 return "unsigned int";
3295 }
3296 else {
3297 return "int";
3298 }
3299 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003300 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003301 return getNameByInfo($1);
3302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003304 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003305}
3306
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003307sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003309 my $Ptd = pointTo($_[0]);
3310 return 0 if(not $Ptd);
3311 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003312 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003313 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3314 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003315 }
3316 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003317 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3318 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003319 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320 if($InfoT1 eq "pointer_type"
3321 and $InfoT2 eq "function_type") {
3322 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
3324 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003325 return 0;
3326}
3327
3328sub isMethodPtr($)
3329{
3330 my $Ptd = pointTo($_[0]);
3331 return 0 if(not $Ptd);
3332 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3333 {
3334 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3335 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3336 and $Info=~/ ptrmem /) {
3337 return 1;
3338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003339 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003340 return 0;
3341}
3342
3343sub isFieldPtr($)
3344{
3345 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3346 {
3347 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3348 and $Info=~/ ptrmem /) {
3349 return 1;
3350 }
3351 }
3352 return 0;
3353}
3354
3355sub pointTo($)
3356{
3357 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3358 {
3359 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3360 return $1;
3361 }
3362 }
3363 return "";
3364}
3365
3366sub getTypeTypeByTypeId($)
3367{
3368 my $TypeId = $_[0];
3369 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3370 {
3371 my $NType = $NodeType{$TType};
3372 if($NType eq "Intrinsic") {
3373 return $NType;
3374 }
3375 elsif(isFuncPtr($TypeId)) {
3376 return "FuncPtr";
3377 }
3378 elsif(isMethodPtr($TypeId)) {
3379 return "MethodPtr";
3380 }
3381 elsif(isFieldPtr($TypeId)) {
3382 return "FieldPtr";
3383 }
3384 elsif($NType ne "Other") {
3385 return $NType;
3386 }
3387 }
3388 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003389}
3390
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003391my %UnQual = (
3392 "r"=>"restrict",
3393 "v"=>"volatile",
3394 "c"=>"const",
3395 "cv"=>"const volatile"
3396);
3397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003398sub getQual($)
3399{
3400 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003401 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3402 {
3403 my ($Qual, $To) = ();
3404 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3405 $Qual = $UnQual{$1};
3406 }
3407 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3408 $To = $1;
3409 }
3410 if($Qual and $To) {
3411 return ($Qual, $To);
3412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003413 }
3414 return ();
3415}
3416
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003417sub getQualType($)
3418{
3419 if($_[0] eq "const volatile") {
3420 return "ConstVolatile";
3421 }
3422 return ucfirst($_[0]);
3423}
3424
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003425sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003426{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003427 my $TypeId = $_[0];
3428 my $TypeDeclId = getTypeDeclId($TypeId);
3429 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003430 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003431 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3432 return "Typedef";
3433 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003434 }
3435 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3436 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003437 if(($Qual or $To) and $TypeDeclId
3438 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003440 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003441 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003442 elsif(not $MissedBase_R{$Version}{$TypeId}
3443 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003444 return "Typedef";
3445 }
3446 elsif($Qual)
3447 { # qualified types
3448 return getQualType($Qual);
3449 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003450
3451 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3452 { # typedef struct { ... } name
3453 $TypeTypedef{$Version}{$TypeId} = $1;
3454 }
3455
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003456 my $TypeType = getTypeTypeByTypeId($TypeId);
3457 if($TypeType eq "Struct")
3458 {
3459 if($TypeDeclId
3460 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3461 return "Template";
3462 }
3463 }
3464 return $TypeType;
3465}
3466
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003467sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003468{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003469 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003471 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3472 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3473 return 0;
3474 }
3475 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3476 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003477 if(my $TDid = getTypeDeclId($_[0]))
3478 {
3479 if(getTypeId($TDid) eq $_[0]
3480 and getNameByInfo($TDid))
3481 {
3482 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3483 return $1;
3484 }
3485 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003487 }
3488 }
3489 return 0;
3490}
3491
3492sub selectBaseType($)
3493{
3494 my $TypeId = $_[0];
3495 if(defined $MissedTypedef{$Version}{$TypeId})
3496 { # add missed typedefs
3497 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3498 return ($TypeId, "");
3499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003500 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003501 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3502 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003503
3504 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3505 my $MB = $MissedBase{$Version}{$TypeId};
3506
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003507 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003508 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 and (getTypeId($1) ne $TypeId)
3510 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003511 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003512 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003513 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003514 elsif($MB)
3515 { # add base
3516 return ($MB, "");
3517 }
3518 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003519 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003520 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003521 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003522 elsif($Qual or $To)
3523 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003524 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003525 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003526 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003527 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003528 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003529 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003531 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003532 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003533 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003534 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003535 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003536 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003537 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003538 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003539 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003540 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003541 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003543 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003544
3545 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003546}
3547
3548sub getSymbolInfo_All()
3549{
3550 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3551 { # reverse order
3552 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003553 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003554 }
3555 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003556
3557 if($ADD_TMPL_INSTANCES)
3558 {
3559 # templates
3560 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3561 {
3562 my %Map = ();
3563
3564 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3565 {
3566 if(defined $TemplateMap{$Version}{$ClassId})
3567 {
3568 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3569 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3570 }
3571 }
3572 }
3573
3574 if(defined $TemplateMap{$Version}{$Sid})
3575 {
3576 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3577 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3578 }
3579 }
3580
3581 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3582 {
3583 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3584 {
3585 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3586 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3587 }
3588 }
3589 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3590 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3591 }
3592 }
3593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003594}
3595
3596sub getVarInfo_All()
3597{
3598 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3599 { # reverse order
3600 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003601 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003602 }
3603 }
3604}
3605
3606sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003607 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003608}
3609
3610sub getVarInfo($)
3611{
3612 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003613 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003614 {
3615 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3616 if($NSInfoType and $NSInfoType eq "function_decl") {
3617 return;
3618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003619 }
3620 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3621 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3622 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3623 delete($SymbolInfo{$Version}{$InfoId});
3624 return;
3625 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003626 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003627 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003628 delete($SymbolInfo{$Version}{$InfoId});
3629 return;
3630 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003631 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3632 delete($SymbolInfo{$Version}{$InfoId});
3633 return;
3634 }
3635 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003636 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3637 {
3638 if($OSgroup eq "windows")
3639 { # cut the offset
3640 $MnglName=~s/\@\d+\Z//g;
3641 }
3642 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003644 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003645 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003646 { # validate mangled name
3647 delete($SymbolInfo{$Version}{$InfoId});
3648 return;
3649 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003650 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003651 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003652 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003653 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003654 }
3655 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3656 { # non-public global data
3657 delete($SymbolInfo{$Version}{$InfoId});
3658 return;
3659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003660 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003662 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003663 if(not defined $TypeInfo{$Version}{$Rid}
3664 or not $TypeInfo{$Version}{$Rid}{"Name"})
3665 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003666 delete($SymbolInfo{$Version}{$InfoId});
3667 return;
3668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003669 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3670 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003671 if(defined $Val) {
3672 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003674 }
3675 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3677 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003678 if(not defined $TypeInfo{$Version}{$ClassId}
3679 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3680 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003681 delete($SymbolInfo{$Version}{$InfoId});
3682 return;
3683 }
3684 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003685 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3686 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003687 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003688 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003690 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003692 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003693 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003694 if(not $CheckHeadersOnly)
3695 {
3696 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3697 {
3698 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3699 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3700 {
3701 if(link_symbol($ShortName, $Version, "-Deps"))
3702 { # "const" global data is mangled as _ZL... in the TU dump
3703 # but not mangled when compiling a C shared library
3704 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3705 }
3706 }
3707 }
3708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709 if($COMMON_LANGUAGE{$Version} eq "C++")
3710 {
3711 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3712 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003713 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003714 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3715 }
3716 }
3717 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3718 { # try to mangle symbol (link with libraries)
3719 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3720 }
3721 if($OStarget eq "windows")
3722 {
3723 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3724 { # link MS C++ symbols from library with GCC symbols from headers
3725 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3726 }
3727 }
3728 }
3729 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3730 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3731 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003732 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3733 {
3734 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3735 { # non-target symbols
3736 delete($SymbolInfo{$Version}{$InfoId});
3737 return;
3738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003739 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003740 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3741 {
3742 if(defined $MissedTypedef{$Version}{$Rid})
3743 {
3744 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3745 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3746 }
3747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003748 }
3749 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003750 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003751 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3752 }
3753 if($ShortName=~/\A(_Z|\?)/) {
3754 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3755 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003756
3757 if($ExtraDump) {
3758 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003760}
3761
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003762sub isConstType($$)
3763{
3764 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003765 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003766 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003767 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003768 }
3769 return ($Base{"Type"} eq "Const");
3770}
3771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003772sub getTrivialName($$)
3773{
3774 my ($TypeInfoId, $TypeId) = @_;
3775 my %TypeAttr = ();
3776 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3777 if(not $TypeAttr{"Name"}) {
3778 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3779 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003780 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003781 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003782 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003783 if(isAnon($TypeAttr{"Name"}))
3784 {
3785 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003786 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003787 { # searching for a first not anon scope
3788 if($NSId eq $NameSpaceId) {
3789 last;
3790 }
3791 else
3792 {
3793 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3794 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003795 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003796 last;
3797 }
3798 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003799 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003800 }
3801 }
3802 else
3803 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003804 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003805 {
3806 if($NameSpaceId ne $TypeId) {
3807 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003809 }
3810 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003811 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3813 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003814 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003815 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003816 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003817 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003818 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003819 if($TypeAttr{"NameSpace"}) {
3820 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003822 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003823 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3824 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003825 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003826 if(my @TParams = getTParams($TypeId, "Type")) {
3827 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3828 }
3829 else {
3830 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003832 }
3833 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3834}
3835
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003836sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003838 my $TypeId = $_[0];
3839 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003840
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003841 my %TypeAttr = ();
3842
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003843 if($TemplateDecl{$Version}{$TypeId})
3844 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003845 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003846 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003847
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003848 setTypeAccess($TypeId, \%TypeAttr);
3849 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3850 if(isBuiltIn($TypeAttr{"Header"}))
3851 {
3852 delete($TypeAttr{"Header"});
3853 delete($TypeAttr{"Line"});
3854 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003855
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003856 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003857 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3858 if(not $TypeAttr{"Name"}) {
3859 return ();
3860 }
3861 if(not $TypeAttr{"NameSpace"}) {
3862 delete($TypeAttr{"NameSpace"});
3863 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003864
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003865 if($TypeAttr{"Type"} eq "Intrinsic")
3866 {
3867 if(defined $TypeAttr{"Header"})
3868 {
3869 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3870 { # support for SUSE 11.2
3871 # integer_type has srcp dump{1-2}.i
3872 delete($TypeAttr{"Header"});
3873 }
3874 }
3875 }
3876
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003877 my $Tmpl = undef;
3878
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003879 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003880 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003881 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3882
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003883 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003884 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003885 foreach my $Pos (0 .. $#TParams)
3886 {
3887 my $Val = $TParams[$Pos];
3888 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3889
3890 if(not defined $TypeAttr{"Template"})
3891 {
3892 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3893
3894 if($Base{"Type"} eq "TemplateParam"
3895 or defined $Base{"Template"}) {
3896 $TypeAttr{"Template"} = 1;
3897 }
3898 }
3899
3900 if($Tmpl)
3901 {
3902 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3903 {
3904 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3905
3906 if($Val eq $Arg) {
3907 $TypeAttr{"Template"} = 1;
3908 }
3909 }
3910 }
3911 }
3912
3913 if($Tmpl)
3914 {
3915 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3916 {
3917 if($Pos>$#TParams)
3918 {
3919 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3920 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3921 }
3922 }
3923 }
3924 }
3925
3926 if($ADD_TMPL_INSTANCES)
3927 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003928 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003929 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003930 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003931 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003932 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003933 {
3934 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3935 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3936 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003937 }
3938 if(not getTreeAttr_Binf($TypeId))
3939 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003940 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3941 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3942 }
3943 }
3944 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003945 }
3946 }
3947 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003948
3949 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3950
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003951 if(my $Size = getSize($TypeId))
3952 {
3953 $Size = $Size/$BYTE_SIZE;
3954 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003955 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003956 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003957 {
3958 if($ExtraDump)
3959 {
3960 if(not defined $TypeAttr{"Memb"}
3961 and not $Tmpl)
3962 { # declaration only
3963 $TypeAttr{"Forward"} = 1;
3964 }
3965 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003966 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003968 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003969 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 {
3971 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003972 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 }
3974 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003975 or $TypeAttr{"Type"} eq "Class")
3976 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003977 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003978 if($Skip) {
3979 return ();
3980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003981 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003982 if(my $Algn = getAlgn($TypeId)) {
3983 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003985 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003986
3987 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3988 {
3989 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003990 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003991 {
3992 if(not isAnon($TypeAttr{"Name"})) {
3993 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3994 }
3995 }
3996 }
3997
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003998 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003999 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4000 {
4001 my @Entries = split(/\n/, $VTable);
4002 foreach (1 .. $#Entries)
4003 {
4004 my $Entry = $Entries[$_];
4005 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004006 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004007 }
4008 }
4009 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004010
4011 if($TypeAttr{"Type"} eq "Enum")
4012 {
4013 if(not $TypeAttr{"NameSpace"})
4014 {
4015 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4016 {
4017 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004018 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004019 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004020 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004021 "Header"=>$TypeAttr{"Header"}
4022 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004023 if(isAnon($TypeAttr{"Name"}))
4024 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004025 if($ExtraDump
4026 or is_target_header($TypeAttr{"Header"}, $Version))
4027 {
4028 %{$Constants{$Version}{$MName}} = (
4029 "Value" => $MVal,
4030 "Header" => $TypeAttr{"Header"}
4031 );
4032 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004033 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004034 }
4035 }
4036 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004037 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004038 {
4039 if(defined $TypedefToAnon{$TypeId}) {
4040 $TypeAttr{"AnonTypedef"} = 1;
4041 }
4042 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004043
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004044 return %TypeAttr;
4045}
4046
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004047sub simplifyVTable($)
4048{
4049 my $Content = $_[0];
4050 if($Content=~s/ \[with (.+)]//)
4051 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4052 if(my @Elems = separate_Params($1, 0, 0))
4053 {
4054 foreach my $Elem (@Elems)
4055 {
4056 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4057 {
4058 my ($Arg, $Val) = ($1, $2);
4059
4060 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4061 $Content=~s/,\s*$Arg\b//g;
4062 }
4063 else {
4064 $Content=~s/\b$Arg\b/$Val/g;
4065 }
4066 }
4067 }
4068 }
4069 }
4070
4071 return $Content;
4072}
4073
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004074sub detect_lang($)
4075{
4076 my $TypeId = $_[0];
4077 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004078 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004079 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004080 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4081 }
4082 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004083 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004084 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004085 while($Fncs)
4086 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004087 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004088 return 1;
4089 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004090 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004091 }
4092 }
4093 return 0;
4094}
4095
4096sub setSpec($$)
4097{
4098 my ($TypeId, $TypeAttr) = @_;
4099 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4100 if($Info=~/\s+spec\s+/) {
4101 $TypeAttr->{"Spec"} = 1;
4102 }
4103}
4104
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004105sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004106{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004107 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004108 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004109 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004110 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004111 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004112 my $Pos = 0;
4113 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4114 {
4115 my ($Access, $BInfoId) = ($1, $2);
4116 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004117
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004118 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004119 { # class A<N>:public A<N-1>
4120 next;
4121 }
4122
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004123 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4124 if(not $CType or $CType eq "template_type_parm"
4125 or $CType eq "typename_type")
4126 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004127 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004129 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004130 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004131 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4132 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004133 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4135 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004136 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004138 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004139 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4140 }
4141 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004142 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004143 }
4144 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004145 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004146}
4147
4148sub getBinfClassId($)
4149{
4150 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004151 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4152 return $1;
4153 }
4154
4155 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004156}
4157
4158sub unmangledFormat($$)
4159{
4160 my ($Name, $LibVersion) = @_;
4161 $Name = uncover_typedefs($Name, $LibVersion);
4162 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4163 $Name=~s/\(\w+\)(\d)/$1/;
4164 return $Name;
4165}
4166
4167sub modelUnmangled($$)
4168{
4169 my ($InfoId, $Compiler) = @_;
4170 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4171 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4172 }
4173 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4174 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4175 $PureSignature = "~".$PureSignature;
4176 }
4177 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4178 {
4179 my (@Params, @ParamTypes) = ();
4180 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4181 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4182 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4183 }
4184 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4185 { # checking parameters
4186 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004187 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004188 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004189 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004190
4191 if($PName eq "this"
4192 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4193 {
4194 next;
4195 }
4196
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004197 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004198 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004199 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004200 }
4201 @ParamTypes = (@ParamTypes, $PTName);
4202 }
4203 if(@ParamTypes) {
4204 $PureSignature .= "(".join(", ", @ParamTypes).")";
4205 }
4206 else
4207 {
4208 if($Compiler eq "MSVC")
4209 {
4210 $PureSignature .= "(void)";
4211 }
4212 else
4213 { # GCC
4214 $PureSignature .= "()";
4215 }
4216 }
4217 $PureSignature = delete_keywords($PureSignature);
4218 }
4219 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4220 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004221 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004222 $PureSignature = $ClassName."::".$PureSignature;
4223 }
4224 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4225 $PureSignature = $NS."::".$PureSignature;
4226 }
4227 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4228 $PureSignature .= " const";
4229 }
4230 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4231 $PureSignature .= " volatile";
4232 }
4233 my $ShowReturn = 0;
4234 if($Compiler eq "MSVC"
4235 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4236 {
4237 $ShowReturn=1;
4238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004239 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4240 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004241 {
4242 $ShowReturn=1;
4243 }
4244 if($ShowReturn)
4245 { # mangled names for template function specializations include return value
4246 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4247 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004248 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4250 $PureSignature = $ReturnName." ".$PureSignature;
4251 }
4252 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004253 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004254}
4255
4256sub mangle_symbol($$$)
4257{ # mangling for simple methods
4258 # see gcc-4.6.0/gcc/cp/mangle.c
4259 my ($InfoId, $LibVersion, $Compiler) = @_;
4260 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4261 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4262 }
4263 my $Mangled = "";
4264 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004265 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004266 }
4267 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004268 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004269 }
4270 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4271}
4272
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004273sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004274{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004275 my ($InfoId, $LibVersion) = @_;
4276 return "";
4277}
4278
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004279sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004280{ # see gcc-4.6.0/gcc/cp/mangle.c
4281 my ($InfoId, $LibVersion) = @_;
4282 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004283 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004284 my %Repl = ();# SN_ replacements
4285 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4286 {
4287 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4288 if($MangledClass!~/\AN/) {
4289 $MangledClass = "N".$MangledClass;
4290 }
4291 else {
4292 $MangledClass=~s/E\Z//;
4293 }
4294 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4295 $MangledClass=~s/\AN/NV/;
4296 }
4297 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4298 $MangledClass=~s/\AN/NK/;
4299 }
4300 $Mangled .= $MangledClass;
4301 }
4302 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4303 { # mangled by name due to the absence of structured info
4304 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4305 if($MangledNS!~/\AN/) {
4306 $MangledNS = "N".$MangledNS;
4307 }
4308 else {
4309 $MangledNS=~s/E\Z//;
4310 }
4311 $Mangled .= $MangledNS;
4312 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004313 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004314 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004315 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004316 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004317 foreach (@TPos) {
4318 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4319 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004320 }
4321 elsif($TmplParams)
4322 { # remangling mode
4323 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004324 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004325 }
4326 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4327 $Mangled .= "C1";
4328 }
4329 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4330 $Mangled .= "D0";
4331 }
4332 elsif($ShortName)
4333 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004334 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4335 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004336 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004337 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004338 { # "const" global data is mangled as _ZL...
4339 $Mangled .= "L";
4340 }
4341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004342 if($ShortName=~/\Aoperator(\W.*)\Z/)
4343 {
4344 my $Op = $1;
4345 $Op=~s/\A[ ]+//g;
4346 if(my $OpMngl = $OperatorMangling{$Op}) {
4347 $Mangled .= $OpMngl;
4348 }
4349 else { # conversion operator
4350 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4351 }
4352 }
4353 else {
4354 $Mangled .= length($ShortName).$ShortName;
4355 }
4356 if(@TParams)
4357 { # templates
4358 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004359 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004360 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4361 }
4362 $Mangled .= "E";
4363 }
4364 if(not $ClassId and @TParams) {
4365 add_substitution($ShortName, \%Repl, 0);
4366 }
4367 }
4368 if($ClassId or $NameSpace) {
4369 $Mangled .= "E";
4370 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004371 if(@TParams)
4372 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004373 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004374 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4375 }
4376 }
4377 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4378 {
4379 my @Params = ();
4380 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4381 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4382 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4383 }
4384 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4385 { # checking parameters
4386 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4387 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4388 }
4389 if(not @Params) {
4390 $Mangled .= "v";
4391 }
4392 }
4393 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4394 $Mangled = write_stdcxx_substitution($Mangled);
4395 if($Mangled eq "_Z") {
4396 return "";
4397 }
4398 return $Mangled;
4399}
4400
4401sub correct_incharge($$$)
4402{
4403 my ($InfoId, $LibVersion, $Mangled) = @_;
4404 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4405 {
4406 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004407 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004408 }
4409 }
4410 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4411 {
4412 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004413 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004414 }
4415 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004416 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004417 }
4418 }
4419 return $Mangled;
4420}
4421
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004422sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004423{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004424 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004425 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004426 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004427 return $Name;
4428 }
4429 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004430 while(my $CPos = find_center($TParams, "<"))
4431 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004432 $TParams = substr($TParams, $CPos);
4433 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004434 if($TParams=~s/\A<(.+)>\Z/$1/) {
4435 $Name=~s/<\Q$TParams\E>\Z//;
4436 }
4437 else
4438 { # error
4439 $TParams = "";
4440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004441 return ($Name, $TParams);
4442}
4443
4444sub get_sub_ns($)
4445{
4446 my $Name = $_[0];
4447 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004448 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004449 {
4450 push(@NS, substr($Name, 0, $CPos));
4451 $Name = substr($Name, $CPos);
4452 $Name=~s/\A:://;
4453 }
4454 return (join("::", @NS), $Name);
4455}
4456
4457sub mangle_ns($$$)
4458{
4459 my ($Name, $LibVersion, $Repl) = @_;
4460 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4461 {
4462 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4463 $Mangled=~s/\AN(.+)E\Z/$1/;
4464 return $Mangled;
4465
4466 }
4467 else
4468 {
4469 my ($MangledNS, $SubNS) = ("", "");
4470 ($SubNS, $Name) = get_sub_ns($Name);
4471 if($SubNS) {
4472 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4473 }
4474 $MangledNS .= length($Name).$Name;
4475 add_substitution($MangledNS, $Repl, 0);
4476 return $MangledNS;
4477 }
4478}
4479
4480sub mangle_param($$$)
4481{
4482 my ($PTid, $LibVersion, $Repl) = @_;
4483 my ($MPrefix, $Mangled) = ("", "");
4484 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004485 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004486 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004487 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004488 if(not $BaseType_Name) {
4489 return "";
4490 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004491 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004492 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004493 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4494 while($Suffix=~/(&|\*|const)\Z/)
4495 {
4496 if($Suffix=~s/[ ]*&\Z//) {
4497 $MPrefix .= "R";
4498 }
4499 if($Suffix=~s/[ ]*\*\Z//) {
4500 $MPrefix .= "P";
4501 }
4502 if($Suffix=~s/[ ]*const\Z//)
4503 {
4504 if($MPrefix=~/R|P/
4505 or $Suffix=~/&|\*/) {
4506 $MPrefix .= "K";
4507 }
4508 }
4509 if($Suffix=~s/[ ]*volatile\Z//) {
4510 $MPrefix .= "V";
4511 }
4512 #if($Suffix=~s/[ ]*restrict\Z//) {
4513 #$MPrefix .= "r";
4514 #}
4515 }
4516 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4517 $Mangled .= $Token;
4518 }
4519 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4520 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004521 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004522 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004523 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004524 foreach (@TPos) {
4525 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4526 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004527 }
4528 elsif($TmplParams)
4529 { # remangling mode
4530 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004531 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004532 }
4533 my $MangledNS = "";
4534 my ($SubNS, $SName) = get_sub_ns($ShortName);
4535 if($SubNS) {
4536 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4537 }
4538 $MangledNS .= length($SName).$SName;
4539 if(@TParams) {
4540 add_substitution($MangledNS, $Repl, 0);
4541 }
4542 $Mangled .= "N".$MangledNS;
4543 if(@TParams)
4544 { # templates
4545 $Mangled .= "I";
4546 foreach my $TParam (@TParams) {
4547 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4548 }
4549 $Mangled .= "E";
4550 }
4551 $Mangled .= "E";
4552 }
4553 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4554 {
4555 if($BaseType{"Type"} eq "MethodPtr") {
4556 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4557 }
4558 else {
4559 $Mangled .= "PF";
4560 }
4561 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4562 my @Params = keys(%{$BaseType{"Param"}});
4563 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4564 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4565 }
4566 if(not @Params) {
4567 $Mangled .= "v";
4568 }
4569 $Mangled .= "E";
4570 }
4571 elsif($BaseType{"Type"} eq "FieldPtr")
4572 {
4573 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4574 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4575 }
4576 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4577 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4578 {
4579 if($Mangled eq $Optimized)
4580 {
4581 if($ShortName!~/::/)
4582 { # remove "N ... E"
4583 if($MPrefix) {
4584 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4585 }
4586 else {
4587 $Mangled=~s/\AN(.+)E\Z/$1/g;
4588 }
4589 }
4590 }
4591 else {
4592 $Mangled = $Optimized;
4593 }
4594 }
4595 add_substitution($Mangled, $Repl, 1);
4596 return $Mangled;
4597}
4598
4599sub mangle_template_param($$$)
4600{ # types + literals
4601 my ($TParam, $LibVersion, $Repl) = @_;
4602 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4603 return mangle_param($TPTid, $LibVersion, $Repl);
4604 }
4605 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4606 { # class_name<1u>::method(...)
4607 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4608 }
4609 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4610 { # class_name<(signed char)1>::method(...)
4611 return "L".$IntrinsicMangling{$1}.$2."E";
4612 }
4613 elsif($TParam eq "true")
4614 { # class_name<true>::method(...)
4615 return "Lb1E";
4616 }
4617 elsif($TParam eq "false")
4618 { # class_name<true>::method(...)
4619 return "Lb0E";
4620 }
4621 else { # internal error
4622 return length($TParam).$TParam;
4623 }
4624}
4625
4626sub add_substitution($$$)
4627{
4628 my ($Value, $Repl, $Rec) = @_;
4629 if($Rec)
4630 { # subtypes
4631 my @Subs = ($Value);
4632 while($Value=~s/\A(R|P|K)//) {
4633 push(@Subs, $Value);
4634 }
4635 foreach (reverse(@Subs)) {
4636 add_substitution($_, $Repl, 0);
4637 }
4638 return;
4639 }
4640 return if($Value=~/\AS(\d*)_\Z/);
4641 $Value=~s/\AN(.+)E\Z/$1/g;
4642 return if(defined $Repl->{$Value});
4643 return if(length($Value)<=1);
4644 return if($StdcxxMangling{$Value});
4645 # check for duplicates
4646 my $Base = $Value;
4647 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4648 {
4649 my $Num = $Repl->{$Type};
4650 my $Replace = macro_mangle($Num);
4651 $Base=~s/\Q$Replace\E/$Type/;
4652 }
4653 if(my $OldNum = $Repl->{$Base})
4654 {
4655 $Repl->{$Value} = $OldNum;
4656 return;
4657 }
4658 my @Repls = sort {$b<=>$a} values(%{$Repl});
4659 if(@Repls) {
4660 $Repl->{$Value} = $Repls[0]+1;
4661 }
4662 else {
4663 $Repl->{$Value} = -1;
4664 }
4665 # register duplicates
4666 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004667 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004668 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4669 {
4670 next if($Base eq $Type);
4671 my $Num = $Repl->{$Type};
4672 my $Replace = macro_mangle($Num);
4673 $Base=~s/\Q$Type\E/$Replace/;
4674 $Repl->{$Base} = $Repl->{$Value};
4675 }
4676}
4677
4678sub macro_mangle($)
4679{
4680 my $Num = $_[0];
4681 if($Num==-1) {
4682 return "S_";
4683 }
4684 else
4685 {
4686 my $Code = "";
4687 if($Num<10)
4688 { # S0_, S1_, S2_, ...
4689 $Code = $Num;
4690 }
4691 elsif($Num>=10 and $Num<=35)
4692 { # SA_, SB_, SC_, ...
4693 $Code = chr(55+$Num);
4694 }
4695 else
4696 { # S10_, S11_, S12_
4697 $Code = $Num-26; # 26 is length of english alphabet
4698 }
4699 return "S".$Code."_";
4700 }
4701}
4702
4703sub write_stdcxx_substitution($)
4704{
4705 my $Mangled = $_[0];
4706 if($StdcxxMangling{$Mangled}) {
4707 return $StdcxxMangling{$Mangled};
4708 }
4709 else
4710 {
4711 my @Repls = keys(%StdcxxMangling);
4712 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4713 foreach my $MangledType (@Repls)
4714 {
4715 my $Replace = $StdcxxMangling{$MangledType};
4716 #if($Mangled!~/$Replace/) {
4717 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4718 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4719 #}
4720 }
4721 }
4722 return $Mangled;
4723}
4724
4725sub write_substitution($$)
4726{
4727 my ($Mangled, $Repl) = @_;
4728 if(defined $Repl->{$Mangled}
4729 and my $MnglNum = $Repl->{$Mangled}) {
4730 $Mangled = macro_mangle($MnglNum);
4731 }
4732 else
4733 {
4734 my @Repls = keys(%{$Repl});
4735 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4736 # FIXME: how to apply replacements? by num or by pos
4737 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4738 foreach my $MangledType (@Repls)
4739 {
4740 my $Replace = macro_mangle($Repl->{$MangledType});
4741 if($Mangled!~/$Replace/) {
4742 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4743 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4744 }
4745 }
4746 }
4747 return $Mangled;
4748}
4749
4750sub delete_keywords($)
4751{
4752 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004753 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004754 return $TypeName;
4755}
4756
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004757sub uncover_typedefs($$)
4758{
4759 my ($TypeName, $LibVersion) = @_;
4760 return "" if(not $TypeName);
4761 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4762 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4763 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004764 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004765 while($TypeName_New ne $TypeName_Pre)
4766 {
4767 $TypeName_Pre = $TypeName_New;
4768 my $TypeName_Copy = $TypeName_New;
4769 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004770 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004771 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004772 if(not $Intrinsic_Keywords{$1}) {
4773 $Words{$1} = 1;
4774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004775 }
4776 foreach my $Word (keys(%Words))
4777 {
4778 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4779 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004780 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004781 if($BaseType_Name=~/\([\*]+\)/)
4782 { # FuncPtr
4783 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4784 {
4785 my $Type_Suffix = $1;
4786 $TypeName_New = $BaseType_Name;
4787 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004788 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004789 }
4790 }
4791 }
4792 else
4793 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004794 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004795 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004796 }
4797 }
4798 }
4799 }
4800 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4801}
4802
4803sub isInternal($)
4804{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004805 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4806 {
4807 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4808 {
4809 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4810 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4811 return 1;
4812 }
4813 }
4814 }
4815 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004816}
4817
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004818sub getDataVal($$)
4819{
4820 my ($InfoId, $TypeId) = @_;
4821 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4822 {
4823 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4824 {
4825 if(defined $LibInfo{$Version}{"info_type"}{$1}
4826 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004827 {
4828 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004829 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004830 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4831 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004832 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004833 if(my $Addr = getTreeAttr_Op($1)) {
4834 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004835 }
4836 }
4837 }
4838 }
4839 else {
4840 return getInitVal($1, $TypeId);
4841 }
4842 }
4843 }
4844 return undef;
4845}
4846
4847sub getInitVal($$)
4848{
4849 my ($InfoId, $TypeId) = @_;
4850 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4851 {
4852 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4853 {
4854 if($InfoType eq "integer_cst")
4855 {
4856 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004857 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004858 { # characters
4859 $Val = chr($Val);
4860 }
4861 return $Val;
4862 }
4863 elsif($InfoType eq "string_cst") {
4864 return getNodeStrCst($InfoId);
4865 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004866 elsif($InfoType eq "var_decl")
4867 {
4868 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4869 return $Name;
4870 }
4871 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004872 }
4873 }
4874 return undef;
4875}
4876
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004877sub set_Class_And_Namespace($)
4878{
4879 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004880 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004881 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004882 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004883 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004884 my $NSInfoId = $1;
4885 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4886 {
4887 if($InfoType eq "namespace_decl") {
4888 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4889 }
4890 elsif($InfoType eq "record_type") {
4891 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4892 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004894 }
4895 }
4896 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4897 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004898 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004899 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004900 { # skip
4901 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004903 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004904
4905 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004906}
4907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004908sub debugMangling($)
4909{
4910 my $LibVersion = $_[0];
4911 my %Mangled = ();
4912 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4913 {
4914 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4915 {
4916 if($Mngl=~/\A(_Z|\?)/) {
4917 $Mangled{$Mngl}=$InfoId;
4918 }
4919 }
4920 }
4921 translateSymbols(keys(%Mangled), $LibVersion);
4922 foreach my $Mngl (keys(%Mangled))
4923 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004924 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4925 my $U2 = $tr_name{$Mngl};
4926 if($U1 ne $U2) {
4927 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004928 }
4929 }
4930}
4931
4932sub linkSymbol($)
4933{ # link symbols from shared libraries
4934 # with the symbols from header files
4935 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004936 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004937 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004938 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4939 or $EMERGENCY_MODE_48)
4940 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4941 # 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 +03004942 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004943 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004944 {
4945 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4946 return correct_incharge($InfoId, $Version, $Mangled);
4947 }
4948 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004949 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004950 or not $BinaryOnly
4951 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004952 { # 1. --headers-only mode
4953 # 2. not mangled src-only symbols
4954 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4955 return $Mangled;
4956 }
4957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004958 }
4959 return "";
4960}
4961
4962sub setLanguage($$)
4963{
4964 my ($LibVersion, $Lang) = @_;
4965 if(not $UserLang) {
4966 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4967 }
4968}
4969
4970sub getSymbolInfo($)
4971{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004972 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004973 if(isInternal($InfoId)) {
4974 return;
4975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004976 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4977 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004978 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4979 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004980 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004981 return;
4982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004983 setFuncAccess($InfoId);
4984 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004985 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4986 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004987 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004988 return;
4989 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004990
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004991 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004992 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004993 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004994 if(not defined $TypeInfo{$Version}{$Return}
4995 or not $TypeInfo{$Version}{$Return}{"Name"})
4996 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004997 delete($SymbolInfo{$Version}{$InfoId});
4998 return;
4999 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005000 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005001 }
5002 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5003 {
5004 if(defined $MissedTypedef{$Version}{$Rid})
5005 {
5006 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5007 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5008 }
5009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005010 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005011 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5012 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005013 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005014 my $Orig = getFuncOrig($InfoId);
5015 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005016 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5017 {
5018 delete($SymbolInfo{$Version}{$InfoId});
5019 return;
5020 }
5021
5022 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005023 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005024 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005025 return;
5026 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005027
5028 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005029 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005030 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5031
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005032 my @TParams = getTParams($Orig, "Func");
5033 if(not @TParams)
5034 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005035 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005036 return;
5037 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005038 foreach my $Pos (0 .. $#TParams)
5039 {
5040 my $Val = $TParams[$Pos];
5041 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5042
5043 if($Tmpl)
5044 {
5045 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5046 {
5047 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5048 }
5049 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005050 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005051
5052 if($Tmpl)
5053 {
5054 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5055 {
5056 if($Pos>$#TParams)
5057 {
5058 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5059 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5060 }
5061 }
5062 }
5063
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005064 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5065 { # operator<< <T>, operator>> <T>
5066 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5067 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005068 if(@TParams) {
5069 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5070 }
5071 else {
5072 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5073 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005074 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005075 }
5076 else
5077 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005078 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005079 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005080 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5081 {
5082 if($OSgroup eq "windows")
5083 { # cut the offset
5084 $MnglName=~s/\@\d+\Z//g;
5085 }
5086 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5087
5088 # NOTE: mangling of some symbols may change depending on GCC version
5089 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5090 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5091 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005092
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005093 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005094 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005095 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005096 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005097 return;
5098 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005099 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005100 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005101 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005102 if($Skip)
5103 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005104 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005105 return;
5106 }
5107 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005108 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5109 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5110 }
5111
5112 if(set_Class_And_Namespace($InfoId))
5113 {
5114 delete($SymbolInfo{$Version}{$InfoId});
5115 return;
5116 }
5117
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005118 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5119 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005120 if(not defined $TypeInfo{$Version}{$ClassId}
5121 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5122 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005123 delete($SymbolInfo{$Version}{$InfoId});
5124 return;
5125 }
5126 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005127 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5128 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005129 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005130 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005131 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005132 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005134 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005135 }
5136 if($COMMON_LANGUAGE{$Version} eq "C++")
5137 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005138 # C++ or --headers-only mode
5139 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005140 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005141 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5142 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005143 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005144 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005146 if(my $Mangled = linkSymbol($InfoId)) {
5147 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005148 }
5149 }
5150 if($OStarget eq "windows")
5151 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005152 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005153 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005154 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005155 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005156 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005157 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005158 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005159 }
5160 }
5161 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005162 else
5163 { # not mangled in C
5164 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5165 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005166 if(not $CheckHeadersOnly
5167 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5168 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5169 {
5170 my $Incorrect = 0;
5171
5172 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5173 {
5174 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5175 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5176 { # mangled in the TU dump, but not mangled in the library
5177 $Incorrect = 1;
5178 }
5179 }
5180 else
5181 {
5182 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5183 { # all C++ functions are not mangled in the TU dump
5184 $Incorrect = 1;
5185 }
5186 }
5187 if($Incorrect)
5188 {
5189 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5190 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5191 }
5192 }
5193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005194 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005195 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005196 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005197 return;
5198 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005199 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005200 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005201 { # identify virtual and pure virtual functions
5202 # NOTE: constructors cannot be virtual
5203 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5204 # in the TU dump, so taking it from the original symbol
5205 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5206 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5207 { # NOTE: D2 destructors are not present in a v-table
5208 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005210 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005211 if(isInline($InfoId)) {
5212 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005213 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005214 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005215 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005217 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5218 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005219 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005220 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005221 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005222 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005223 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005224 }
5225 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005226 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5227 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005228 if(not $ExtraDump)
5229 {
5230 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5231 { # non-target symbols
5232 delete($SymbolInfo{$Version}{$InfoId});
5233 return;
5234 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005236 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005237 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5238 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5239 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5240 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005242 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5243 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005244 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 return;
5246 }
5247 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005251 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005252 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 return;
5254 }
5255 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005257 }
5258 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5260 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5261 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005263 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5264 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005267 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005268 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005269 }
5270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005271 if(getFuncLink($InfoId) eq "Static") {
5272 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005273 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005274 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5275 {
5276 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5277 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005278 if($Unmangled=~/\.\_\d/)
5279 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005280 delete($SymbolInfo{$Version}{$InfoId});
5281 return;
5282 }
5283 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005285
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005286 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5287 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005288 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005289 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5290 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005291 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005292
5293 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5294 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5295 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005296
5297 if($ExtraDump) {
5298 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5299 }
5300}
5301
5302sub guessHeader($)
5303{
5304 my $InfoId = $_[0];
5305 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5306 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5307 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5308 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5309 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5310 {
5311 if(get_filename($HPath) eq $Header)
5312 {
5313 my $HDir = get_filename(get_dirname($HPath));
5314 if($HDir ne "include"
5315 and $HDir=~/\A[a-z]+\Z/i) {
5316 return join_P($HDir, $Header);
5317 }
5318 }
5319 }
5320 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005321}
5322
5323sub isInline($)
5324{ # "body: undefined" in the tree
5325 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005326 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5327 {
5328 if($Info=~/ undefined /i) {
5329 return 0;
5330 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005331 }
5332 return 1;
5333}
5334
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005335sub hasThrow($)
5336{
5337 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5338 {
5339 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5340 return getTreeAttr_Unql($1, "unql");
5341 }
5342 }
5343 return 1;
5344}
5345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005346sub getTypeId($)
5347{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005348 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5349 {
5350 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5351 return $1;
5352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005353 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005354 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355}
5356
5357sub setTypeMemb($$)
5358{
5359 my ($TypeId, $TypeAttr) = @_;
5360 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005361 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005362 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005363 if($TypeType eq "Enum")
5364 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005365 my $MInfoId = getTreeAttr_Csts($TypeId);
5366 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005367 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005368 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5369 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005370 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005371 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5372 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005373 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005374 }
5375 }
5376 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5377 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005378 my $MInfoId = getTreeAttr_Flds($TypeId);
5379 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005381 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5382 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005383 if(not $IType or $IType ne "field_decl")
5384 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005385
5386 if($IType eq "var_decl")
5387 { # static field
5388 $StaticFields = 1;
5389 }
5390
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005391 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005392 next;
5393 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005394 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005395 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005396 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005397 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005398 }
5399 if(not $StructMembName)
5400 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005401 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005403 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005404 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5405 if(isAnon($UnnamedTName))
5406 { # rename unnamed fields to unnamed0, unnamed1, ...
5407 $StructMembName = "unnamed".($UnnamedPos++);
5408 }
5409 }
5410 }
5411 if(not $StructMembName)
5412 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005413 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 next;
5415 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005416 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005417 if(defined $MissedTypedef{$Version}{$MembTypeId})
5418 {
5419 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5420 $MembTypeId = $AddedTid;
5421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005422 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005423
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005424 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5425 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005426 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005427 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005428 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5429 }
5430 if($MInfo=~/spec:\s*mutable /)
5431 { # mutable fields
5432 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005434 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005435 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5436 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005437 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005438 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005439 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005440 }
5441 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005442 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005443 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5444 { # template
5445 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5446 }
5447 else {
5448 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005450 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005451
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005452 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005453 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005454 }
5455 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005456
5457 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005458}
5459
5460sub setFuncParams($)
5461{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005462 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005463 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005464
5465 my $FType = getFuncType($InfoId);
5466
5467 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005468 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005469 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5470 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005471 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005472 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005473 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005475 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005476 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5477 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005478 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005479 else
5480 { # skip
5481 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005483 # skip "this"-parameter
5484 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005485 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005486 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005487 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005488 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005489 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5490 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5491 if(not $ParamName)
5492 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005493 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005494 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005495 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5496 {
5497 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5498 $ParamTypeId = $AddedTid;
5499 }
5500 }
5501 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 if(not $PType or $PType eq "Unknown") {
5503 return 1;
5504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005505 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005506 if(not $PTName) {
5507 return 1;
5508 }
5509 if($PTName eq "void") {
5510 last;
5511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005513 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005514 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005515 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005516 $ParamInfoId = getNextElem($ParamInfoId);
5517 next;
5518 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005519 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005520
5521 if(my %Base = get_BaseType($ParamTypeId, $Version))
5522 {
5523 if(defined $Base{"Template"}) {
5524 return 1;
5525 }
5526 }
5527
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005528 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005529 if(my $Algn = getAlgn($ParamInfoId)) {
5530 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005532 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5533 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005534 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005535 }
5536 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005538 if($ParamName ne "this" or $FType ne "Method") {
5539 $PPos += 1;
5540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005542 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005543 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005544 }
5545 return 0;
5546}
5547
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005548sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005549{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005550 my ($InfoId, $Vtt_Pos) = @_;
5551 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005552 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005553 my $FType = getFuncType($InfoId);
5554
5555 if($FType eq "Method")
5556 {
5557 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005558 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005560 if(not $ParamListElemId)
5561 { # foo(...)
5562 return 1;
5563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005564 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005565 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005566 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005567 { # actual params: may differ from formal args
5568 # formal int*const
5569 # actual: int*
5570 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 {
5572 $Vtt_Pos=-1;
5573 $ParamListElemId = getNextElem($ParamListElemId);
5574 next;
5575 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005576 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5577 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005578 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005579 $HaveVoid = 1;
5580 last;
5581 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005582 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005583 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005584 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5585 {
5586 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5587 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5588 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005589 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005590 }
5591 }
5592 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5593 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005594 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005595 { # params
5596 if($OldId ne $ParamTypeId)
5597 {
5598 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5599 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5600
5601 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5602 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5603 }
5604 }
5605 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005606 }
5607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005608 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005610 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5611 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005612 if($PurpType eq "nop_expr")
5613 { # func ( const char* arg = (const char*)(void*)0 )
5614 $PurpId = getTreeAttr_Op($PurpId);
5615 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005616 my $Val = getInitVal($PurpId, $ParamTypeId);
5617 if(defined $Val) {
5618 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620 }
5621 }
5622 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005623 if($Pos!=0 or $FType ne "Method") {
5624 $PPos += 1;
5625 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005626 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005627 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005628 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005629}
5630
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005631sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005633 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5634 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005635 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5636 return $1;
5637 }
5638 }
5639 return "";
5640}
5641
5642sub getTreeAttr_Chain($)
5643{
5644 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5645 {
5646 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5647 return $1;
5648 }
5649 }
5650 return "";
5651}
5652
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005653sub getTreeAttr_Unql($)
5654{
5655 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5656 {
5657 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5658 return $1;
5659 }
5660 }
5661 return "";
5662}
5663
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005664sub getTreeAttr_Scpe($)
5665{
5666 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5667 {
5668 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5669 return $1;
5670 }
5671 }
5672 return "";
5673}
5674
5675sub getTreeAttr_Type($)
5676{
5677 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5678 {
5679 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5680 return $1;
5681 }
5682 }
5683 return "";
5684}
5685
5686sub getTreeAttr_Name($)
5687{
5688 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5689 {
5690 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5691 return $1;
5692 }
5693 }
5694 return "";
5695}
5696
5697sub getTreeAttr_Mngl($)
5698{
5699 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5700 {
5701 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5702 return $1;
5703 }
5704 }
5705 return "";
5706}
5707
5708sub getTreeAttr_Prms($)
5709{
5710 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5711 {
5712 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5713 return $1;
5714 }
5715 }
5716 return "";
5717}
5718
5719sub getTreeAttr_Fncs($)
5720{
5721 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5722 {
5723 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5724 return $1;
5725 }
5726 }
5727 return "";
5728}
5729
5730sub getTreeAttr_Csts($)
5731{
5732 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5733 {
5734 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5735 return $1;
5736 }
5737 }
5738 return "";
5739}
5740
5741sub getTreeAttr_Purp($)
5742{
5743 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5744 {
5745 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5746 return $1;
5747 }
5748 }
5749 return "";
5750}
5751
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005752sub getTreeAttr_Op($)
5753{
5754 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5755 {
5756 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5757 return $1;
5758 }
5759 }
5760 return "";
5761}
5762
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005763sub getTreeAttr_Valu($)
5764{
5765 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5766 {
5767 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5768 return $1;
5769 }
5770 }
5771 return "";
5772}
5773
5774sub getTreeAttr_Flds($)
5775{
5776 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5777 {
5778 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5779 return $1;
5780 }
5781 }
5782 return "";
5783}
5784
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005785sub getTreeAttr_Binf($)
5786{
5787 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5788 {
5789 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5790 return $1;
5791 }
5792 }
5793 return "";
5794}
5795
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005796sub getTreeAttr_Args($)
5797{
5798 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5799 {
5800 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005801 return $1;
5802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005803 }
5804 return "";
5805}
5806
5807sub getTreeValue($)
5808{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005809 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5810 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005811 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5812 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005814 }
5815 return "";
5816}
5817
5818sub getTreeAccess($)
5819{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005820 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005821 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005822 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5823 {
5824 my $Access = $1;
5825 if($Access eq "prot") {
5826 return "protected";
5827 }
5828 elsif($Access eq "priv") {
5829 return "private";
5830 }
5831 }
5832 elsif($Info=~/ protected /)
5833 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005834 return "protected";
5835 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005836 elsif($Info=~/ private /)
5837 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005838 return "private";
5839 }
5840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005841 return "public";
5842}
5843
5844sub setFuncAccess($)
5845{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005846 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005847 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005848 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005849 }
5850 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005851 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005852 }
5853}
5854
5855sub setTypeAccess($$)
5856{
5857 my ($TypeId, $TypeAttr) = @_;
5858 my $Access = getTreeAccess($TypeId);
5859 if($Access eq "protected") {
5860 $TypeAttr->{"Protected"} = 1;
5861 }
5862 elsif($Access eq "private") {
5863 $TypeAttr->{"Private"} = 1;
5864 }
5865}
5866
5867sub setFuncKind($)
5868{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005869 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5870 {
5871 if($Info=~/pseudo tmpl/) {
5872 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5873 }
5874 elsif($Info=~/ constructor /) {
5875 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5876 }
5877 elsif($Info=~/ destructor /) {
5878 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005880 }
5881}
5882
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005883sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005884{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005885 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5886 {
5887 if($Info=~/spec[ ]*:[ ]*pure /) {
5888 return "PureVirt";
5889 }
5890 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5891 return "Virt";
5892 }
5893 elsif($Info=~/ pure\s+virtual /)
5894 { # support for old GCC versions
5895 return "PureVirt";
5896 }
5897 elsif($Info=~/ virtual /)
5898 { # support for old GCC versions
5899 return "Virt";
5900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005901 }
5902 return "";
5903}
5904
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005905sub getFuncLink($)
5906{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005907 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5908 {
5909 if($Info=~/link[ ]*:[ ]*static /) {
5910 return "Static";
5911 }
5912 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913 return $1;
5914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005915 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005916 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005917}
5918
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005919sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005920{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005921 my ($Symbol, $LibVersion) = @_;
5922 return "" if(not $Symbol or not $LibVersion);
5923 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5924 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005925 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005926 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5927 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5928 }
5929 }
5930 if($NS)
5931 {
5932 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5933 return $NS;
5934 }
5935 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937 while($NS=~s/::[^:]+\Z//)
5938 {
5939 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5940 return $NS;
5941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942 }
5943 }
5944 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005945
5946 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005947}
5948
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005949sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950{
5951 my ($TypeName, $LibVersion) = @_;
5952 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005953 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005955 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5956 return $NS;
5957 }
5958 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005959 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005960 while($NS=~s/::[^:]+\Z//)
5961 {
5962 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5963 return $NS;
5964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005965 }
5966 }
5967 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005968 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005969}
5970
5971sub getNameSpace($)
5972{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005973 my $InfoId = $_[0];
5974 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005975 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005976 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005977 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005978 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005979 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005980 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5981 {
5982 my $NameSpace = getTreeStr($1);
5983 if($NameSpace eq "::")
5984 { # global namespace
5985 return "";
5986 }
5987 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5988 $NameSpace = $BaseNameSpace."::".$NameSpace;
5989 }
5990 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5991 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005992 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005993 else {
5994 return "";
5995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005997 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005998 { # inside data type
5999 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6000 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006004 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006005}
6006
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006007sub getEnumMembVal($)
6008{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006009 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006011 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6012 {
6013 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6014 {
6015 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6016 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6017 return getTreeValue($1);
6018 }
6019 else
6020 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6021 return getTreeValue($1);
6022 }
6023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 }
6025 }
6026 return "";
6027}
6028
6029sub getSize($)
6030{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006031 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6032 {
6033 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6034 return getTreeValue($1);
6035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006036 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006037 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038}
6039
6040sub getAlgn($)
6041{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006042 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6043 {
6044 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6045 return $1;
6046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006047 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006048 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006049}
6050
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006051sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006053 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6054 {
6055 if($Info=~/ bitfield /) {
6056 return getSize($_[0]);
6057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006058 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006059 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006060}
6061
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006062sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006064 if(my $Chan = getTreeAttr_Chan($_[0])) {
6065 return $Chan;
6066 }
6067 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6068 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006069 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006070 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071}
6072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006073sub registerHeader($$)
6074{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006075 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006076 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077 return "";
6078 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006079 if(is_abs($Header) and not -f $Header)
6080 { # incorrect absolute path
6081 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006082 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006083 if(skipHeader($Header, $LibVersion))
6084 { # skip
6085 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006087 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6088 {
6089 detect_header_includes($Header_Path, $LibVersion);
6090
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006091 if(defined $Tolerance and $Tolerance=~/3/)
6092 { # 3 - skip headers that include non-Linux headers
6093 if($OSgroup ne "windows")
6094 {
6095 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6096 {
6097 if(specificHeader($Inc, "windows")) {
6098 return "";
6099 }
6100 }
6101 }
6102 }
6103
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006104 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6105 { # redirect
6106 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6107 or skipHeader($RHeader_Path, $LibVersion))
6108 { # skip
6109 return "";
6110 }
6111 $Header_Path = $RHeader_Path;
6112 }
6113 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6114 { # skip
6115 return "";
6116 }
6117
6118 if(my $HName = get_filename($Header_Path))
6119 { # register
6120 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6121 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6122 }
6123
6124 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6125 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006126 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006127 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006128 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006129 }
6130
6131 if($CheckHeadersOnly
6132 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6133 { # /usr/include/c++/4.6.1/...
6134 $STDCXX_TESTING = 1;
6135 }
6136
6137 return $Header_Path;
6138 }
6139 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006140}
6141
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006142sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006143{
6144 my ($Dir, $WithDeps, $LibVersion) = @_;
6145 $Dir=~s/[\/\\]+\Z//g;
6146 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006147 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006149 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006150 if($WithDeps)
6151 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6153 return;
6154 }
6155 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6156 $Mode = "DepsOnly";
6157 }
6158 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006159 else
6160 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006161 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6162 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6163 return;
6164 }
6165 }
6166 $Header_Dependency{$LibVersion}{$Dir} = 1;
6167 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6168 if($Mode eq "DepsOnly")
6169 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006170 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006171 $Header_Dependency{$LibVersion}{$Path} = 1;
6172 }
6173 return;
6174 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006175 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006176 {
6177 if($WithDeps)
6178 {
6179 my $SubDir = $Path;
6180 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6181 { # register all sub directories
6182 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6183 }
6184 }
6185 next if(is_not_header($Path));
6186 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006187 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006188 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006189 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6190 }
6191 }
6192 if(get_filename($Dir) eq "include")
6193 { # search for "lib/include/" directory
6194 my $LibDir = $Dir;
6195 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006196 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006197 }
6198 }
6199}
6200
6201sub parse_redirect($$$)
6202{
6203 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006204 my @Errors = ();
6205 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6206 push(@Errors, $1);
6207 }
6208 my $Redirect = "";
6209 foreach (@Errors)
6210 {
6211 s/\s{2,}/ /g;
6212 if(/(only|must\ include
6213 |update\ to\ include
6214 |replaced\ with
6215 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006216 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006217 {
6218 $Redirect = $2;
6219 last;
6220 }
6221 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6222 {
6223 $Redirect = $2;
6224 last;
6225 }
6226 elsif(/this\ header\ should\ not\ be\ used
6227 |programs\ should\ not\ directly\ include
6228 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6229 |is\ not\ supported\ API\ for\ general\ use
6230 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006231 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006232 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6233 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6234 }
6235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006236 if($Redirect)
6237 {
6238 $Redirect=~s/\A<//g;
6239 $Redirect=~s/>\Z//g;
6240 }
6241 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006242}
6243
6244sub parse_includes($$)
6245{
6246 my ($Content, $Path) = @_;
6247 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006248 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006249 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006250 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006251 my $Method = substr($Header, 0, 1, "");
6252 substr($Header, length($Header)-1, 1, "");
6253 $Header = path_format($Header, $OSgroup);
6254 if($Method eq "\"" or is_abs($Header))
6255 {
6256 if(-e join_P(get_dirname($Path), $Header))
6257 { # relative path exists
6258 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006259 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006260 else
6261 { # include "..." that doesn't exist is equal to include <...>
6262 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006264 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006265 else {
6266 $Includes{$Header} = 1;
6267 }
6268 }
6269 if($ExtraInfo)
6270 {
6271 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6272 { # FT_FREETYPE_H
6273 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006274 }
6275 }
6276 return \%Includes;
6277}
6278
6279sub ignore_path($)
6280{
6281 my $Path = $_[0];
6282 if($Path=~/\~\Z/)
6283 {# skipping system backup files
6284 return 1;
6285 }
6286 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6287 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6288 return 1;
6289 }
6290 return 0;
6291}
6292
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006293sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006294{
6295 my ($ArrRef, $W) = @_;
6296 return if(length($W)<2);
6297 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6298}
6299
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006300sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006301{
6302 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006303
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006304 $H1=~s/\.[a-z]+\Z//ig;
6305 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006306
6307 my $Hname1 = get_filename($H1);
6308 my $Hname2 = get_filename($H2);
6309 my $HDir1 = get_dirname($H1);
6310 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311 my $Dirname1 = get_filename($HDir1);
6312 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006313
6314 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6315 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6316
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006317 if($_[0] eq $_[1]
6318 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006319 return 0;
6320 }
6321 elsif($H1=~/\A\Q$H2\E/) {
6322 return 1;
6323 }
6324 elsif($H2=~/\A\Q$H1\E/) {
6325 return -1;
6326 }
6327 elsif($HDir1=~/\Q$Hname1\E/i
6328 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006329 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006330 return -1;
6331 }
6332 elsif($HDir2=~/\Q$Hname2\E/i
6333 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006334 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006335 return 1;
6336 }
6337 elsif($Hname1=~/\Q$Dirname1\E/i
6338 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006339 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006340 return -1;
6341 }
6342 elsif($Hname2=~/\Q$Dirname2\E/i
6343 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006344 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006345 return 1;
6346 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006347 elsif($Hname1=~/(config|lib|util)/i
6348 and $Hname2!~/(config|lib|util)/i)
6349 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006350 return -1;
6351 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006352 elsif($Hname2=~/(config|lib|util)/i
6353 and $Hname1!~/(config|lib|util)/i)
6354 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006355 return 1;
6356 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006357 else
6358 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006359 my $R1 = checkRelevance($H1);
6360 my $R2 = checkRelevance($H2);
6361 if($R1 and not $R2)
6362 { # libebook/e-book.h
6363 return -1;
6364 }
6365 elsif($R2 and not $R1)
6366 { # libebook/e-book.h
6367 return 1;
6368 }
6369 else
6370 {
6371 return (lc($H1) cmp lc($H2));
6372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006373 }
6374}
6375
6376sub searchForHeaders($)
6377{
6378 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006380 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006381 registerGccHeaders();
6382
6383 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6384 { # c++ standard include paths
6385 registerCppHeaders();
6386 }
6387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006388 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006389 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6390 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 {
6392 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006393 if($SystemRoot)
6394 {
6395 if(is_abs($Path)) {
6396 $Path = $SystemRoot.$Path;
6397 }
6398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 if(not -e $Path) {
6400 exitStatus("Access_Error", "can't access \'$Path\'");
6401 }
6402 elsif(-f $Path) {
6403 exitStatus("Access_Error", "\'$Path\' - not a directory");
6404 }
6405 elsif(-d $Path)
6406 {
6407 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006408 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006409 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6410 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006411 }
6412 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006413 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006414 }
6415 }
6416 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006417 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006418 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6419 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006420
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 # registering directories
6422 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6423 {
6424 next if(not -e $Path);
6425 $Path = get_abs_path($Path);
6426 $Path = path_format($Path, $OSgroup);
6427 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006428 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006429 }
6430 elsif(-f $Path)
6431 {
6432 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006433 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006434 and not $LocalIncludes{$Dir})
6435 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006436 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006437 # if(my $OutDir = get_dirname($Dir))
6438 # { # registering the outer directory
6439 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6440 # and not $LocalIncludes{$OutDir}) {
6441 # registerDir($OutDir, 0, $LibVersion);
6442 # }
6443 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006444 }
6445 }
6446 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006447
6448 # clean memory
6449 %RegisteredDirs = ();
6450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006451 # registering headers
6452 my $Position = 0;
6453 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6454 {
6455 if(is_abs($Dest) and not -e $Dest) {
6456 exitStatus("Access_Error", "can't access \'$Dest\'");
6457 }
6458 $Dest = path_format($Dest, $OSgroup);
6459 if(is_header($Dest, 1, $LibVersion))
6460 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006461 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006462 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6463 }
6464 }
6465 elsif(-d $Dest)
6466 {
6467 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006468 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006469 {
6470 next if(ignore_path($Path));
6471 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006472 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006473 push(@Registered, $HPath);
6474 }
6475 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006476 @Registered = sort {sortHeaders($a, $b)} @Registered;
6477 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006478 foreach my $Path (@Registered) {
6479 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6480 }
6481 }
6482 else {
6483 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6484 }
6485 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006486
6487 if(defined $Tolerance and $Tolerance=~/4/)
6488 { # 4 - skip headers included by others
6489 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6490 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006491 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006492 delete($Registered_Headers{$LibVersion}{$Path});
6493 }
6494 }
6495 }
6496
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006497 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6498 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006499 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006500 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006501 if(is_abs($Header) and not -f $Header) {
6502 exitStatus("Access_Error", "can't access file \'$Header\'");
6503 }
6504 $Header = path_format($Header, $OSgroup);
6505 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6506 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006507 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006508 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006509 }
6510 else {
6511 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006513 }
6514 }
6515 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6516 { # set relative paths (for duplicates)
6517 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6518 { # search for duplicates
6519 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6520 my $Prefix = get_dirname($FirstPath);
6521 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6522 { # detect a shortest distinguishing prefix
6523 my $NewPrefix = $1;
6524 my %Identity = ();
6525 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6526 {
6527 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6528 $Identity{$Path} = $1;
6529 }
6530 }
6531 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006532 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006533 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6534 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6535 }
6536 last;
6537 }
6538 $Prefix = $NewPrefix; # increase prefix
6539 }
6540 }
6541 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006542
6543 # clean memory
6544 %HeaderName_Paths = ();
6545
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006546 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6547 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006548 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006549 my ($Pos, $PairPos) = (-1, -1);
6550 my ($Path, $PairPath) = ();
6551 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6552 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6553 foreach my $Header_Path (@Paths)
6554 {
6555 if(get_filename($Header_Path) eq $PairName)
6556 {
6557 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6558 $PairPath = $Header_Path;
6559 }
6560 if(get_filename($Header_Path) eq $HeaderName)
6561 {
6562 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6563 $Path = $Header_Path;
6564 }
6565 }
6566 if($PairPos!=-1 and $Pos!=-1
6567 and int($PairPos)<int($Pos))
6568 {
6569 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6570 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6571 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6572 }
6573 }
6574 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6575 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6576 }
6577}
6578
6579sub detect_real_includes($$)
6580{
6581 my ($AbsPath, $LibVersion) = @_;
6582 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6583 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6584 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6585 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6586 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006587 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6588
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006589 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6590 return () if(not $Path);
6591 open(PREPROC, $Path);
6592 while(<PREPROC>)
6593 {
6594 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6595 {
6596 my $Include = path_format($1, $OSgroup);
6597 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6598 next;
6599 }
6600 if($Include eq $AbsPath) {
6601 next;
6602 }
6603 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6604 }
6605 }
6606 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6608}
6609
6610sub detect_header_includes($$)
6611{
6612 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006613 return if(not $LibVersion or not $Path);
6614 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6615 return;
6616 }
6617 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6618
6619 if(not -e $Path) {
6620 return;
6621 }
6622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006623 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006624 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6625 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006626 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006627 {
6628 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006629 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006630 }
6631 if($RedirectPath ne $Path) {
6632 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6633 }
6634 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006635 else
6636 { # can't find
6637 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006639 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006640 if(my $Inc = parse_includes($Content, $Path))
6641 {
6642 foreach my $Include (keys(%{$Inc}))
6643 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006644 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006645
6646 if(defined $Tolerance and $Tolerance=~/4/)
6647 {
6648 if(my $HPath = identifyHeader($Include, $LibVersion))
6649 {
6650 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6651 }
6652 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006655}
6656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006657sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006658{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006659 my $Path = $_[0];
6660 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006661 if($OStarget eq "symbian")
6662 {
6663 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6664 { # epoc32/include/libc/{stdio, ...}.h
6665 return 1;
6666 }
6667 }
6668 else
6669 {
6670 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6671 { # /usr/include/{stdio, ...}.h
6672 return 1;
6673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006675 return 0;
6676}
6677
6678sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006679{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006680 my $Dir = $_[0];
6681 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006682 if($OStarget eq "symbian")
6683 {
6684 if(get_filename($OutDir) eq "libc"
6685 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6686 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6687 return 1;
6688 }
6689 }
6690 else
6691 { # linux
6692 if($OutDir eq "/usr/include"
6693 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6694 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6695 return 1;
6696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006697 }
6698 return 0;
6699}
6700
6701sub detect_recursive_includes($$)
6702{
6703 my ($AbsPath, $LibVersion) = @_;
6704 return () if(not $AbsPath);
6705 if(isCyclical(\@RecurInclude, $AbsPath)) {
6706 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6707 }
6708 my ($AbsDir, $Name) = separate_path($AbsPath);
6709 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006710 { # system GLIBC internals
6711 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006712 }
6713 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6714 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6715 }
6716 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006717
6718 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6719 { # skip /usr/include/c++/*/ headers
6720 return () if(not $ExtraInfo);
6721 }
6722
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006724 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006725 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006726 { # check "real" (non-"model") include paths
6727 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6728 pop(@RecurInclude);
6729 return @Paths;
6730 }
6731 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6732 detect_header_includes($AbsPath, $LibVersion);
6733 }
6734 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6735 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006736 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006737 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006738 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006739 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006740 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006741 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006742 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006743 }
6744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006745 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006746 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006747 { # search for the nearest header
6748 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006749 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006750 if(-f $Candidate) {
6751 $HPath = $Candidate;
6752 }
6753 }
6754 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006755 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006756 }
6757 next if(not $HPath);
6758 if($HPath eq $AbsPath) {
6759 next;
6760 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006761
6762 if($Debug)
6763 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006764# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6765# {
6766# print STDERR "$AbsPath -> $HPath\n";
6767# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006768 }
6769
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006770 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6771 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 { # only include <...>, skip include "..." prefixes
6773 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6774 }
6775 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6776 {
6777 if($IncPath eq $AbsPath) {
6778 next;
6779 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006780 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6781 if($RIncType==-1)
6782 { # include "..."
6783 $RIncType = $IncType;
6784 }
6785 elsif($RIncType==2)
6786 {
6787 if($IncType!=-1) {
6788 $RIncType = $IncType;
6789 }
6790 }
6791 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006792 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6793 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6794 }
6795 }
6796 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6797 {
6798 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6799 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6800 { # distinguish math.h from glibc and math.h from the tested library
6801 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6802 last;
6803 }
6804 }
6805 }
6806 pop(@RecurInclude);
6807 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6808}
6809
6810sub find_in_framework($$$)
6811{
6812 my ($Header, $Framework, $LibVersion) = @_;
6813 return "" if(not $Header or not $Framework or not $LibVersion);
6814 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6815 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6816 }
6817 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6818 {
6819 if(get_filename($Dependency) eq $Framework
6820 and -f get_dirname($Dependency)."/".$Header) {
6821 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6822 }
6823 }
6824 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6825}
6826
6827sub find_in_defaults($)
6828{
6829 my $Header = $_[0];
6830 return "" if(not $Header);
6831 if(defined $Cache{"find_in_defaults"}{$Header}) {
6832 return $Cache{"find_in_defaults"}{$Header};
6833 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006834 foreach my $Dir (@DefaultIncPaths,
6835 @DefaultGccPaths,
6836 @DefaultCppPaths,
6837 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006838 {
6839 next if(not $Dir);
6840 if(-f $Dir."/".$Header) {
6841 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6842 }
6843 }
6844 return ($Cache{"find_in_defaults"}{$Header}="");
6845}
6846
6847sub cmp_paths($$)
6848{
6849 my ($Path1, $Path2) = @_;
6850 my @Parts1 = split(/[\/\\]/, $Path1);
6851 my @Parts2 = split(/[\/\\]/, $Path2);
6852 foreach my $Num (0 .. $#Parts1)
6853 {
6854 my $Part1 = $Parts1[$Num];
6855 my $Part2 = $Parts2[$Num];
6856 if($GlibcDir{$Part1}
6857 and not $GlibcDir{$Part2}) {
6858 return 1;
6859 }
6860 elsif($GlibcDir{$Part2}
6861 and not $GlibcDir{$Part1}) {
6862 return -1;
6863 }
6864 elsif($Part1=~/glib/
6865 and $Part2!~/glib/) {
6866 return 1;
6867 }
6868 elsif($Part1!~/glib/
6869 and $Part2=~/glib/) {
6870 return -1;
6871 }
6872 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6873 return $CmpRes;
6874 }
6875 }
6876 return 0;
6877}
6878
6879sub checkRelevance($)
6880{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006881 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006882 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006883
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006884 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006885 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006887
6888 my $Name = lc(get_filename($Path));
6889 my $Dir = lc(get_dirname($Path));
6890
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006891 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006892
6893 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006894 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006895 my $Len = length($Token);
6896 next if($Len<=1);
6897 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6898 { # include/evolution-data-server-1.4/libebook/e-book.h
6899 return 1;
6900 }
6901 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006902 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006903 return 1;
6904 }
6905 }
6906 return 0;
6907}
6908
6909sub checkFamily(@)
6910{
6911 my @Paths = @_;
6912 return 1 if($#Paths<=0);
6913 my %Prefix = ();
6914 foreach my $Path (@Paths)
6915 {
6916 if($SystemRoot) {
6917 $Path = cut_path_prefix($Path, $SystemRoot);
6918 }
6919 if(my $Dir = get_dirname($Path))
6920 {
6921 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6922 $Prefix{$Dir} += 1;
6923 $Prefix{get_dirname($Dir)} += 1;
6924 }
6925 }
6926 foreach (sort keys(%Prefix))
6927 {
6928 if(get_depth($_)>=3
6929 and $Prefix{$_}==$#Paths+1) {
6930 return 1;
6931 }
6932 }
6933 return 0;
6934}
6935
6936sub isAcceptable($$$)
6937{
6938 my ($Header, $Candidate, $LibVersion) = @_;
6939 my $HName = get_filename($Header);
6940 if(get_dirname($Header))
6941 { # with prefix
6942 return 1;
6943 }
6944 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6945 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6946 return 1;
6947 }
6948 if(checkRelevance($Candidate))
6949 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6950 return 1;
6951 }
6952 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6953 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6954 # /usr/include/qt4/Qt/qsslconfiguration.h
6955 return 1;
6956 }
6957 if($OStarget eq "symbian")
6958 {
6959 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6960 return 1;
6961 }
6962 }
6963 return 0;
6964}
6965
6966sub isRelevant($$$)
6967{ # disallow to search for "abstract" headers in too deep directories
6968 my ($Header, $Candidate, $LibVersion) = @_;
6969 my $HName = get_filename($Header);
6970 if($OStarget eq "symbian")
6971 {
6972 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6973 return 0;
6974 }
6975 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006976 if($OStarget ne "bsd")
6977 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006978 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6979 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6980 return 0;
6981 }
6982 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006983 if($OStarget ne "windows")
6984 {
6985 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6986 { # skip /usr/include/wine/msvcrt
6987 return 0;
6988 }
6989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006990 if(not get_dirname($Header)
6991 and $Candidate=~/[\/\\]wx[\/\\]/)
6992 { # do NOT search in system /wx/ directory
6993 # for headers without a prefix: sstream.h
6994 return 0;
6995 }
6996 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6997 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6998 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6999 return 0;
7000 }
7001 if($Candidate=~/[\/\\]asm-/
7002 and (my $Arch = getArch($LibVersion)) ne "unknown")
7003 { # arch-specific header files
7004 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7005 {# skip ../asm-arm/ if using x86 architecture
7006 return 0;
7007 }
7008 }
7009 my @Candidates = getSystemHeaders($HName, $LibVersion);
7010 if($#Candidates==1)
7011 { # unique header
7012 return 1;
7013 }
7014 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7015 if($#SCandidates==1)
7016 { # unique name
7017 return 1;
7018 }
7019 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7020 if(get_depth($Candidate)-$SystemDepth>=5)
7021 { # abstract headers in too deep directories
7022 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7023 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7024 return 0;
7025 }
7026 }
7027 if($Header eq "parser.h"
7028 and $Candidate!~/\/libxml2\//)
7029 { # select parser.h from xml2 library
7030 return 0;
7031 }
7032 if(not get_dirname($Header)
7033 and keys(%{$SystemHeaders{$HName}})>=3)
7034 { # many headers with the same name
7035 # like thread.h included without a prefix
7036 if(not checkFamily(@Candidates)) {
7037 return 0;
7038 }
7039 }
7040 return 1;
7041}
7042
7043sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007044{ # cache function
7045 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7046 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7047 }
7048 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7049}
7050
7051sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007052{
7053 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007054 if(-f $Header) {
7055 return $Header;
7056 }
7057 if(is_abs($Header) and not -f $Header)
7058 { # incorrect absolute path
7059 return "";
7060 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007061 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007062 { # too abstract configuration headers
7063 return "";
7064 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007065 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007066 if($OSgroup ne "windows")
7067 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007068 if(defined $WinHeaders{lc($HName)}
7069 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007070 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007071 return "";
7072 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007073 }
7074 if($OSgroup ne "macos")
7075 {
7076 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007077 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007078 return "";
7079 }
7080 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007081
7082 if(defined $ObsoleteHeaders{$HName})
7083 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007084 return "";
7085 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007086 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7087 {
7088 if(defined $AlienHeaders{$HName}
7089 or defined $AlienHeaders{$Header})
7090 { # alien headers from other systems
7091 return "";
7092 }
7093 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007094
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007095 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007096 { # search in default paths
7097 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007098 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007099 }
7100 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007101 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007102 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007103 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007104 }
7105 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7106 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7107 {
7108 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007109 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007110 }
7111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007112 # error
7113 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007114}
7115
7116sub getSystemHeaders($$)
7117{
7118 my ($Header, $LibVersion) = @_;
7119 my @Candidates = ();
7120 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7121 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007122 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007123 next;
7124 }
7125 push(@Candidates, $Candidate);
7126 }
7127 return @Candidates;
7128}
7129
7130sub cut_path_prefix($$)
7131{
7132 my ($Path, $Prefix) = @_;
7133 return $Path if(not $Prefix);
7134 $Prefix=~s/[\/\\]+\Z//;
7135 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7136 return $Path;
7137}
7138
7139sub is_default_include_dir($)
7140{
7141 my $Dir = $_[0];
7142 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007143 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007144}
7145
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007146sub identifyHeader($$)
7147{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007149 if(not $Header) {
7150 return "";
7151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007152 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007153 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7154 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007156 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007157}
7158
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007159sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007160{ # search for header by absolute path, relative path or name
7161 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007162 if(-f $Header)
7163 { # it's relative or absolute path
7164 return get_abs_path($Header);
7165 }
7166 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7167 and my $HeaderDir = find_in_defaults($Header))
7168 { # search for libc headers in the /usr/include
7169 # for non-libc target library before searching
7170 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007171 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 }
7173 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7174 { # search in the target library paths
7175 return $Path;
7176 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007177 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007178 { # search in the internal GCC include paths
7179 return $DefaultGccHeader{$Header};
7180 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007181 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007182 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007183 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007184 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007185 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007186 { # search in the default G++ include paths
7187 return $DefaultCppHeader{$Header};
7188 }
7189 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7190 { # search everywhere in the system
7191 return $AnyPath;
7192 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007193 elsif($OSgroup eq "macos")
7194 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7195 if(my $Dir = get_dirname($Header))
7196 {
7197 my $RelPath = "Headers\/".get_filename($Header);
7198 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007199 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007200 }
7201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007203 # cannot find anything
7204 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007205}
7206
7207sub getLocation($)
7208{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007209 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7210 {
7211 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007212 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007214 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007215 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007216}
7217
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007218sub getNameByInfo($)
7219{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007220 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007221 {
7222 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7223 {
7224 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7225 {
7226 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7227 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007228 my $Str = $1;
7229 if($CppMode{$Version}
7230 and $Str=~/\Ac99_(.+)\Z/)
7231 {
7232 if($CppKeywords_A{$1}) {
7233 $Str=$1;
7234 }
7235 }
7236 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007237 }
7238 }
7239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007240 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007241 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007242}
7243
7244sub getTreeStr($)
7245{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007247 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007248 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7249 {
7250 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007251 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007252 and $Str=~/\Ac99_(.+)\Z/)
7253 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007254 if($CppKeywords_A{$1}) {
7255 $Str=$1;
7256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007257 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007258 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007260 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007261 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007262}
7263
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007264sub getFuncShortName($)
7265{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007266 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007268 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007269 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007270 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007271 {
7272 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7273 {
7274 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7275 return "operator ".$RName;
7276 }
7277 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007278 }
7279 else
7280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007281 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7282 {
7283 if(my $Ind = $Operator_Indication{$1}) {
7284 return "operator".$Ind;
7285 }
7286 elsif(not $UnknownOperator{$1})
7287 {
7288 printMsg("WARNING", "unknown operator $1");
7289 $UnknownOperator{$1} = 1;
7290 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007291 }
7292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293 }
7294 else
7295 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007296 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7297 return getTreeStr($1);
7298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007299 }
7300 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007301 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302}
7303
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007304sub getFuncReturn($)
7305{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007306 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7307 {
7308 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7309 {
7310 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7311 return $1;
7312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313 }
7314 }
7315 return "";
7316}
7317
7318sub getFuncOrig($)
7319{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007320 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7321 {
7322 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7323 return $1;
7324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007325 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007326 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327}
7328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007329sub unmangleArray(@)
7330{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007331 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007332 { # MSVC mangling
7333 my $UndNameCmd = get_CmdPath("undname");
7334 if(not $UndNameCmd) {
7335 exitStatus("Not_Found", "can't find \"undname\"");
7336 }
7337 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007338 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007339 }
7340 else
7341 { # GCC mangling
7342 my $CppFiltCmd = get_CmdPath("c++filt");
7343 if(not $CppFiltCmd) {
7344 exitStatus("Not_Found", "can't find c++filt in PATH");
7345 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007346 if(not defined $CPPFILT_SUPPORT_FILE)
7347 {
7348 my $Info = `$CppFiltCmd -h 2>&1`;
7349 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7350 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007351 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007352 if($CPPFILT_SUPPORT_FILE)
7353 { # new versions of c++filt can take a file
7354 if($#_>$MAX_CPPFILT_FILE_SIZE)
7355 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7356 # this is fixed in the oncoming version of Binutils
7357 my @Half = splice(@_, 0, ($#_+1)/2);
7358 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007359 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007360 else
7361 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007362 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7363 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7364 if($?==139)
7365 { # segmentation fault
7366 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7367 }
7368 return split(/\n/, $Res);
7369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007370 }
7371 else
7372 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007373 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7374 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007375 my @Half = splice(@_, 0, ($#_+1)/2);
7376 return (unmangleArray(@Half), unmangleArray(@_))
7377 }
7378 else
7379 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007380 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007381 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7382 if($?==139)
7383 { # segmentation fault
7384 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7385 }
7386 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387 }
7388 }
7389 }
7390}
7391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007392sub get_ChargeLevel($$)
7393{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007394 my ($Symbol, $LibVersion) = @_;
7395 return "" if($Symbol!~/\A(_Z|\?)/);
7396 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7397 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007399 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007401 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007402 return "[in-charge]";
7403 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007404 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405 return "[not-in-charge]";
7406 }
7407 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007408 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007410 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007411 return "[in-charge]";
7412 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007413 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007414 return "[not-in-charge]";
7415 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007416 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007417 return "[in-charge-deleting]";
7418 }
7419 }
7420 }
7421 else
7422 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007423 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007424 return "[in-charge]";
7425 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007426 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007427 return "[not-in-charge]";
7428 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007429 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430 return "[in-charge]";
7431 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007432 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007433 return "[not-in-charge]";
7434 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007435 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436 return "[in-charge-deleting]";
7437 }
7438 }
7439 return "";
7440}
7441
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007442sub get_Signature_M($$)
7443{
7444 my ($Symbol, $LibVersion) = @_;
7445 my $Signature_M = $tr_name{$Symbol};
7446 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7447 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007448 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007449 }
7450 return $Signature_M;
7451}
7452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453sub get_Signature($$)
7454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007455 my ($Symbol, $LibVersion) = @_;
7456 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7457 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007459 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007460 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007461
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007462 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007463
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007464 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007466 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7467 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007468 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7469 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007470
7471 if(index($Symbol, "_ZTV")==0) {
7472 return "vtable for $ClassName [data]";
7473 }
7474
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007475 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007476 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7477 $Signature .= "~";
7478 }
7479 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007480 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007481 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007482 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007483 }
7484 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007485 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007486 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007487 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7488 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007490 else
7491 {
7492 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007493 }
7494 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007495 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007496 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007497 if($Pos eq "") {
7498 next;
7499 }
7500
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007501 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007502 if(not $ParamTypeId) {
7503 next;
7504 }
7505
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007506 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007507 if(not $ParamTypeName) {
7508 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7509 }
7510 foreach my $Typedef (keys(%ChangedTypedef))
7511 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007512 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7513 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007515 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007516 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7517 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007518 if($ParamName eq "this"
7519 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007520 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007521 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007522 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007523 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 }
7525 else {
7526 push(@ParamArray, $ParamTypeName);
7527 }
7528 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007529 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7530 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007531 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007532 }
7533 else
7534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007535 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007537 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007538 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007539 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007540 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7541 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007542 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007543 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007544 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7545 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007546 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007548 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7549 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007550 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007551 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 }
7553 }
7554 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007555 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007556 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 }
7558 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007559 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007560 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007561 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007562}
7563
7564sub create_member_decl($$)
7565{
7566 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007567 if($TName=~/\([\*]+\)/)
7568 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7570 return $TName;
7571 }
7572 else
7573 {
7574 my @ArraySizes = ();
7575 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7576 push(@ArraySizes, $1);
7577 }
7578 return $TName." ".$Member.join("", @ArraySizes);
7579 }
7580}
7581
7582sub getFuncType($)
7583{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007584 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7585 {
7586 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7587 {
7588 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7589 {
7590 if($Type eq "method_type") {
7591 return "Method";
7592 }
7593 elsif($Type eq "function_type") {
7594 return "Function";
7595 }
7596 else {
7597 return "Other";
7598 }
7599 }
7600 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007601 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007602 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007603}
7604
7605sub getFuncTypeId($)
7606{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007607 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7608 {
7609 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7610 return $1;
7611 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007612 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007613 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007614}
7615
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007616sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007617{ # "._N" or "$_N" in older GCC versions
7618 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619}
7620
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007621sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007622{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007623 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7624 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007625 }
7626
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007627 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007628
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007629 if($_[1] ne "S")
7630 {
7631 $N=~s/\A[ ]+//g;
7632 $N=~s/[ ]+\Z//g;
7633 $N=~s/[ ]{2,}/ /g;
7634 }
7635
7636 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007637
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007638 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7639
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007640 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007641
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007642 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7643 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007644
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007645 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007646
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007647 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007648
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007649 if($_[1] eq "S")
7650 {
7651 if(index($N, "operator")!=-1) {
7652 $N=~s/\b(operator[ ]*)> >/$1>>/;
7653 }
7654 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007655
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007656 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007657
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007658 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007659}
7660
7661sub get_HeaderDeps($$)
7662{
7663 my ($AbsPath, $LibVersion) = @_;
7664 return () if(not $AbsPath or not $LibVersion);
7665 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7666 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7667 }
7668 my %IncDir = ();
7669 detect_recursive_includes($AbsPath, $LibVersion);
7670 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7671 {
7672 next if(not $HeaderPath);
7673 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7674 my $Dir = get_dirname($HeaderPath);
7675 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7676 {
7677 my $Dep = $Dir;
7678 if($Prefix)
7679 {
7680 if($OSgroup eq "windows")
7681 { # case insensitive seach on windows
7682 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7683 next;
7684 }
7685 }
7686 elsif($OSgroup eq "macos")
7687 { # seach in frameworks
7688 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7689 {
7690 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7691 {# frameworks
7692 my ($HFramework, $HName) = ($1, $2);
7693 $Dep = $HFramework;
7694 }
7695 else
7696 {# mismatch
7697 next;
7698 }
7699 }
7700 }
7701 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7702 { # Linux, FreeBSD
7703 next;
7704 }
7705 }
7706 if(not $Dep)
7707 { # nothing to include
7708 next;
7709 }
7710 if(is_default_include_dir($Dep))
7711 { # included by the compiler
7712 next;
7713 }
7714 if(get_depth($Dep)==1)
7715 { # too short
7716 next;
7717 }
7718 if(isLibcDir($Dep))
7719 { # do NOT include /usr/include/{sys,bits}
7720 next;
7721 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007722 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007723 }
7724 }
7725 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7726 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7727}
7728
7729sub sortIncPaths($$)
7730{
7731 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007732 if(not $ArrRef or $#{$ArrRef}<0) {
7733 return $ArrRef;
7734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007735 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7736 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007737 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007738 return $ArrRef;
7739}
7740
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007741sub sortDeps($$$)
7742{
7743 if($Header_Dependency{$_[2]}{$_[0]}
7744 and not $Header_Dependency{$_[2]}{$_[1]}) {
7745 return 1;
7746 }
7747 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7748 and $Header_Dependency{$_[2]}{$_[1]}) {
7749 return -1;
7750 }
7751 return 0;
7752}
7753
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007754sub join_P($$)
7755{
7756 my $S = "/";
7757 if($OSgroup eq "windows") {
7758 $S = "\\";
7759 }
7760 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007761}
7762
7763sub get_namespace_additions($)
7764{
7765 my $NameSpaces = $_[0];
7766 my ($Additions, $AddNameSpaceId) = ("", 1);
7767 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7768 {
7769 next if($SkipNameSpaces{$Version}{$NS});
7770 next if(not $NS or $NameSpaces->{$NS}==-1);
7771 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7772 next if($NS=~/\A__/i);
7773 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007774 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007775 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7776 my @NS_Parts = split(/::/, $NS);
7777 next if($#NS_Parts==-1);
7778 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7779 foreach my $NS_Part (@NS_Parts)
7780 {
7781 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7782 $TypeDecl_Suffix .= "}";
7783 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007784 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007785 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7786 $Additions.=" $TypeDecl\n $FuncDecl\n";
7787 $AddNameSpaceId+=1;
7788 }
7789 return $Additions;
7790}
7791
7792sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007793{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007794 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007795 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007796 if($Fmt eq "windows")
7797 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007798 $Path=~s/\//\\/g;
7799 $Path=lc($Path);
7800 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007801 else
7802 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007803 $Path=~s/\\/\//g;
7804 }
7805 return $Path;
7806}
7807
7808sub inc_opt($$)
7809{
7810 my ($Path, $Style) = @_;
7811 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007812 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007813 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007814 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007815 return "-I\"".path_format($Path, "unix")."\"";
7816 }
7817 elsif($OSgroup eq "macos"
7818 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007819 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007820 return "-F".esc(get_dirname($Path));
7821 }
7822 else {
7823 return "-I".esc($Path);
7824 }
7825 }
7826 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007827 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007828 }
7829 return "";
7830}
7831
7832sub platformSpecs($)
7833{
7834 my $LibVersion = $_[0];
7835 my $Arch = getArch($LibVersion);
7836 if($OStarget eq "symbian")
7837 { # options for GCCE compiler
7838 my %Symbian_Opts = map {$_=>1} (
7839 "-D__GCCE__",
7840 "-DUNICODE",
7841 "-fexceptions",
7842 "-D__SYMBIAN32__",
7843 "-D__MARM_INTERWORK__",
7844 "-D_UNICODE",
7845 "-D__S60_50__",
7846 "-D__S60_3X__",
7847 "-D__SERIES60_3X__",
7848 "-D__EPOC32__",
7849 "-D__MARM__",
7850 "-D__EABI__",
7851 "-D__MARM_ARMV5__",
7852 "-D__SUPPORT_CPP_EXCEPTIONS__",
7853 "-march=armv5t",
7854 "-mapcs",
7855 "-mthumb-interwork",
7856 "-DEKA2",
7857 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7858 );
7859 return join(" ", keys(%Symbian_Opts));
7860 }
7861 elsif($OSgroup eq "windows"
7862 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7863 { # add options to MinGW compiler
7864 # to simulate the MSVC compiler
7865 my %MinGW_Opts = map {$_=>1} (
7866 "-D_WIN32",
7867 "-D_STDCALL_SUPPORTED",
7868 "-D__int64=\"long long\"",
7869 "-D__int32=int",
7870 "-D__int16=short",
7871 "-D__int8=char",
7872 "-D__possibly_notnullterminated=\" \"",
7873 "-D__nullterminated=\" \"",
7874 "-D__nullnullterminated=\" \"",
7875 "-D__w64=\" \"",
7876 "-D__ptr32=\" \"",
7877 "-D__ptr64=\" \"",
7878 "-D__forceinline=inline",
7879 "-D__inline=inline",
7880 "-D__uuidof(x)=IID()",
7881 "-D__try=",
7882 "-D__except(x)=",
7883 "-D__declspec(x)=__attribute__((x))",
7884 "-D__pragma(x)=",
7885 "-D_inline=inline",
7886 "-D__forceinline=__inline",
7887 "-D__stdcall=__attribute__((__stdcall__))",
7888 "-D__cdecl=__attribute__((__cdecl__))",
7889 "-D__fastcall=__attribute__((__fastcall__))",
7890 "-D__thiscall=__attribute__((__thiscall__))",
7891 "-D_stdcall=__attribute__((__stdcall__))",
7892 "-D_cdecl=__attribute__((__cdecl__))",
7893 "-D_fastcall=__attribute__((__fastcall__))",
7894 "-D_thiscall=__attribute__((__thiscall__))",
7895 "-DSHSTDAPI_(x)=x",
7896 "-D_MSC_EXTENSIONS",
7897 "-DSECURITY_WIN32",
7898 "-D_MSC_VER=1500",
7899 "-D_USE_DECLSPECS_FOR_SAL",
7900 "-D__noop=\" \"",
7901 "-DDECLSPEC_DEPRECATED=\" \"",
7902 "-D__builtin_alignof(x)=__alignof__(x)",
7903 "-DSORTPP_PASS");
7904 if($Arch eq "x86") {
7905 $MinGW_Opts{"-D_M_IX86=300"}=1;
7906 }
7907 elsif($Arch eq "x86_64") {
7908 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7909 }
7910 elsif($Arch eq "ia64") {
7911 $MinGW_Opts{"-D_M_IA64=300"}=1;
7912 }
7913 return join(" ", keys(%MinGW_Opts));
7914 }
7915 return "";
7916}
7917
7918my %C_Structure = map {$_=>1} (
7919# FIXME: Can't separate union and struct data types before dumping,
7920# so it sometimes cause compilation errors for unknown reason
7921# when trying to declare TYPE* tmp_add_class_N
7922# This is a list of such structures + list of other C structures
7923 "sigval",
7924 "sigevent",
7925 "sigaction",
7926 "sigvec",
7927 "sigstack",
7928 "timeval",
7929 "timezone",
7930 "rusage",
7931 "rlimit",
7932 "wait",
7933 "flock",
7934 "stat",
7935 "_stat",
7936 "stat32",
7937 "_stat32",
7938 "stat64",
7939 "_stat64",
7940 "_stati64",
7941 "if_nameindex",
7942 "usb_device",
7943 "sigaltstack",
7944 "sysinfo",
7945 "timeLocale",
7946 "tcp_debug",
7947 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007948 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007949 "timespec",
7950 "random_data",
7951 "drand48_data",
7952 "_IO_marker",
7953 "_IO_FILE",
7954 "lconv",
7955 "sched_param",
7956 "tm",
7957 "itimerspec",
7958 "_pthread_cleanup_buffer",
7959 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007960 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007961 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007962 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007963 "sigcontext",
7964 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007965 # Mac
7966 "_timex",
7967 "_class_t",
7968 "_category_t",
7969 "_class_ro_t",
7970 "_protocol_t",
7971 "_message_ref_t",
7972 "_super_message_ref_t",
7973 "_ivar_t",
7974 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007975);
7976
7977sub getCompileCmd($$$)
7978{
7979 my ($Path, $Opt, $Inc) = @_;
7980 my $GccCall = $GCC_PATH;
7981 if($Opt) {
7982 $GccCall .= " ".$Opt;
7983 }
7984 $GccCall .= " -x ";
7985 if($OSgroup eq "macos") {
7986 $GccCall .= "objective-";
7987 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007988
7989 if($EMERGENCY_MODE_48)
7990 { # workaround for GCC 4.8 (C only)
7991 $GccCall .= "c++";
7992 }
7993 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007994 { # compile as "C++" header
7995 # to obtain complete dump using GCC 4.0
7996 $GccCall .= "c++-header";
7997 }
7998 else
7999 { # compile as "C++" source
8000 # GCC 3.3 cannot compile headers
8001 $GccCall .= "c++";
8002 }
8003 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008004 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008005 $GccCall .= " ".$Opts;
8006 }
8007 # allow extra qualifications
8008 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008009 $GccCall .= " -fpermissive";
8010 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008011 if($NoStdInc)
8012 {
8013 $GccCall .= " -nostdinc";
8014 $GccCall .= " -nostdinc++";
8015 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008016 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008017 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008018 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008019 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008020 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008021 if($Inc)
8022 { # include paths
8023 $GccCall .= " ".$Inc;
8024 }
8025 return $GccCall;
8026}
8027
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008028sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008029{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008030 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008031 my %HeaderElems = (
8032 # Types
8033 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008034 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008035 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8036 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008037 "time.h" => ["time_t"],
8038 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008039 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8040 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008041 "stdbool.h" => ["_Bool"],
8042 "rpc/xdr.h" => ["bool_t"],
8043 "in_systm.h" => ["n_long", "n_short"],
8044 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008045 "arpa/inet.h" => ["fw_src", "ip_src"],
8046 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008047 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008048 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008049 );
8050 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008051 foreach (keys(%HeaderElems))
8052 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008053 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008054 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008055 }
8056 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008057 my %Types = ();
8058 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8059 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008060 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008061 }
8062 if(keys(%Types))
8063 {
8064 my %AddHeaders = ();
8065 foreach my $Type (keys(%Types))
8066 {
8067 if(my $Header = $AutoPreamble{$Type})
8068 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008069 if(my $Path = identifyHeader($Header, $LibVersion))
8070 {
8071 if(skipHeader($Path, $LibVersion)) {
8072 next;
8073 }
8074 $Path = path_format($Path, $OSgroup);
8075 $AddHeaders{$Path}{"Type"} = $Type;
8076 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008077 }
8078 }
8079 }
8080 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008081 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008082 }
8083 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008084 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008085}
8086
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008087sub checkCTags($)
8088{
8089 my $Path = $_[0];
8090 if(not $Path) {
8091 return;
8092 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008093 my $CTags = undef;
8094
8095 if($OSgroup eq "bsd")
8096 { # use ectags on BSD
8097 $CTags = get_CmdPath("ectags");
8098 if(not $CTags) {
8099 printMsg("WARNING", "can't find \'ectags\' program");
8100 }
8101 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008102 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008103 $CTags = get_CmdPath("ctags");
8104 }
8105 if(not $CTags)
8106 {
8107 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008108 return;
8109 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008110
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008111 if($OSgroup ne "linux")
8112 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008113 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8114 if($Info!~/exuberant/i)
8115 {
8116 printMsg("WARNING", "incompatible version of \'ctags\' program");
8117 return;
8118 }
8119 }
8120
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008121 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008122 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008123 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008124 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008125 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008126 open(CTAGS, "<", $Out);
8127 while(my $Line = <CTAGS>)
8128 {
8129 chomp($Line);
8130 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008131 if(defined $Intrinsic_Keywords{$Name})
8132 { # noise
8133 next;
8134 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008135 if($Type eq "n")
8136 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008137 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008138 next;
8139 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008140 if(index($Scpe, "struct:")==0) {
8141 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008142 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008143 if(index($Scpe, "namespace:")==0)
8144 {
8145 if($Scpe=~s/\Anamespace://) {
8146 $Name = $Scpe."::".$Name;
8147 }
8148 }
8149 $TUnit_NameSpaces{$Version}{$Name} = 1;
8150 }
8151 elsif($Type eq "p")
8152 {
8153 if(not $Scpe or index($Scpe, "namespace:")==0) {
8154 $TUnit_Funcs{$Version}{$Name} = 1;
8155 }
8156 }
8157 elsif($Type eq "x")
8158 {
8159 if(not $Scpe or index($Scpe, "namespace:")==0) {
8160 $TUnit_Vars{$Version}{$Name} = 1;
8161 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008162 }
8163 }
8164 close(CTAGS);
8165}
8166
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008167sub preChange($$)
8168{
8169 my ($HeaderPath, $IncStr) = @_;
8170
8171 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8172 my $Content = undef;
8173
8174 if($OStarget eq "windows"
8175 and get_dumpmachine($GCC_PATH)=~/mingw/i
8176 and $MinGWMode{$Version}!=-1)
8177 { # modify headers to compile by MinGW
8178 if(not $Content)
8179 { # preprocessing
8180 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8181 }
8182 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8183 { # __asm { ... }
8184 $MinGWMode{$Version}=1;
8185 }
8186 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8187 { # comments after preprocessing
8188 $MinGWMode{$Version}=1;
8189 }
8190 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8191 { # 0xffui8
8192 $MinGWMode{$Version}=1;
8193 }
8194
8195 if($MinGWMode{$Version}) {
8196 printMsg("INFO", "Using MinGW compatibility mode");
8197 }
8198 }
8199
8200 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8201 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8202 { # rename C++ keywords in C code
8203 # disable this code by -cpp-compatible option
8204 if(not $Content)
8205 { # preprocessing
8206 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8207 }
8208 my $RegExp_C = join("|", keys(%CppKeywords_C));
8209 my $RegExp_F = join("|", keys(%CppKeywords_F));
8210 my $RegExp_O = join("|", keys(%CppKeywords_O));
8211
8212 my $Detected = undef;
8213
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008214 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 +04008215 { # MATCH:
8216 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008217 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008218 # unsigned private: 8;
8219 # DO NOT MATCH:
8220 # #pragma GCC visibility push(default)
8221 $CppMode{$Version} = 1;
8222 $Detected = "$1$2$3$4" if(not defined $Detected);
8223 }
8224 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8225 { # MATCH:
8226 # int delete(...);
8227 # int explicit(...);
8228 # DO NOT MATCH:
8229 # void operator delete(...)
8230 $CppMode{$Version} = 1;
8231 $Detected = "$1$2$3" if(not defined $Detected);
8232 }
8233 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8234 { # MATCH:
8235 # int bool;
8236 # DO NOT MATCH:
8237 # bool X;
8238 # return *this;
8239 # throw;
8240 $CppMode{$Version} = 1;
8241 $Detected = "$1$2$3" if(not defined $Detected);
8242 }
8243 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8244 { # MATCH:
8245 # int operator(...);
8246 # DO NOT MATCH:
8247 # int operator()(...);
8248 $CppMode{$Version} = 1;
8249 $Detected = "$1$2$3" if(not defined $Detected);
8250 }
8251 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8252 { # MATCH:
8253 # int foo(int operator);
8254 # int foo(int operator, int other);
8255 # DO NOT MATCH:
8256 # int operator,(...);
8257 $CppMode{$Version} = 1;
8258 $Detected = "$1$2$3" if(not defined $Detected);
8259 }
8260 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8261 { # MATCH:
8262 # int foo(gboolean *bool);
8263 # DO NOT MATCH:
8264 # void setTabEnabled(int index, bool);
8265 $CppMode{$Version} = 1;
8266 $Detected = "$1$2$3" if(not defined $Detected);
8267 }
8268 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8269 { # MATCH:
8270 # int foo(int* this);
8271 # int bar(int this);
8272 # int baz(int throw);
8273 # DO NOT MATCH:
8274 # foo(X, this);
8275 $CppMode{$Version} = 1;
8276 $Detected = "$1$2$3$4" if(not defined $Detected);
8277 }
8278 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8279 { # MATCH:
8280 # struct template {...};
8281 # extern template foo(...);
8282 $CppMode{$Version} = 1;
8283 $Detected = "$1$2" if(not defined $Detected);
8284 }
8285
8286 if($CppMode{$Version} == 1)
8287 {
8288 if($Debug)
8289 {
8290 $Detected=~s/\A\s+//g;
8291 printMsg("INFO", "Detected code: \"$Detected\"");
8292 }
8293 }
8294
8295 # remove typedef enum NAME NAME;
8296 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8297 my $N = 0;
8298 while($N<=$#FwdTypedefs-1)
8299 {
8300 my $S = $FwdTypedefs[$N];
8301 if($S eq $FwdTypedefs[$N+1])
8302 {
8303 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008304 $CppMode{$Version} = 1;
8305
8306 if($Debug) {
8307 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8308 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008309 }
8310 $N+=2;
8311 }
8312
8313 if($CppMode{$Version}==1) {
8314 printMsg("INFO", "Using C++ compatibility mode");
8315 }
8316 }
8317
8318 if($CppMode{$Version}==1
8319 or $MinGWMode{$Version}==1)
8320 {
8321 my $IPath = $TMP_DIR."/dump$Version.i";
8322 writeFile($IPath, $Content);
8323 return $IPath;
8324 }
8325
8326 return undef;
8327}
8328
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008329sub getDump()
8330{
8331 if(not $GCC_PATH) {
8332 exitStatus("Error", "internal error - GCC path is not set");
8333 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008334
8335 my @Headers = keys(%{$Registered_Headers{$Version}});
8336 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8337
8338 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8339
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008340 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008341 my $HeaderPath = $TmpHeaderPath;
8342
8343 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008344 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008345 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8346 {
8347 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008348 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008349 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008350 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008351 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8352 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008353 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008354 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008355 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008356 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8357 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008359 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008360 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008361
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008362 if($ExtraInfo)
8363 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008364 if($IncludeString) {
8365 writeFile($ExtraInfo."/include-string", $IncludeString);
8366 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008367 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8368 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008369
8370 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8371 {
8372 my $REDIR = "";
8373 foreach my $P1 (sort @Redirects) {
8374 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8375 }
8376 writeFile($ExtraInfo."/include-redirect", $REDIR);
8377 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008378 }
8379
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008380 if(not keys(%{$TargetHeaders{$Version}}))
8381 { # Target headers
8382 addTargetHeaders($Version);
8383 }
8384
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008385 # clean memory
8386 %RecursiveIncludes = ();
8387 %Header_Include_Prefix = ();
8388 %Header_Includes = ();
8389
8390 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008391 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008392 delete($Cache{"detect_header_includes"});
8393 delete($Cache{"selectSystemHeader"});
8394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008395 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008396 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8397 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008398
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008399 if($ExtraInfo)
8400 { # extra information for other tools
8401 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8402 }
8403
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008404 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008405 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008406 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008407
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008408 if($COMMON_LANGUAGE{$Version} eq "C++") {
8409 checkCTags($Pre);
8410 }
8411
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008412 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8413 { # try to correct the preprocessor output
8414 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008415 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008416
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008417 if($COMMON_LANGUAGE{$Version} eq "C++")
8418 { # add classes and namespaces to the dump
8419 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008420 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008421 or $MinGWMode{$Version}==1) {
8422 $CHdump .= " -fpreprocessed";
8423 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008424 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008425 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008426 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008427 chdir($ORIG_DIR);
8428 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8429 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008430 my $Content = readFile($ClassDump);
8431 foreach my $ClassInfo (split(/\n\n/, $Content))
8432 {
8433 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8434 {
8435 my $CName = $1;
8436 next if($CName=~/\A(__|_objc_|_opaque_)/);
8437 $TUnit_NameSpaces{$Version}{$CName} = -1;
8438 if($CName=~/\A[\w:]+\Z/)
8439 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008440 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008441 }
8442 if($CName=~/(\w[\w:]*)::/)
8443 { # namespaces
8444 my $NS = $1;
8445 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8446 $TUnit_NameSpaces{$Version}{$NS} = 1;
8447 }
8448 }
8449 }
8450 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8451 { # read v-tables (advanced approach)
8452 my ($CName, $VTable) = ($1, $2);
8453 $ClassVTable_Content{$Version}{$CName} = $VTable;
8454 }
8455 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008456 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8457 { # add user-defined namespaces
8458 $TUnit_NameSpaces{$Version}{$NS} = 1;
8459 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008460 if($Debug)
8461 { # debug mode
8462 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008463 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008464 }
8465 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008466 }
8467
8468 # add namespaces and classes
8469 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8470 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008471 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008472 }
8473 # some GCC versions don't include class methods to the TU dump by default
8474 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008475 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008476 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8477 {
8478 next if($C_Structure{$CName});
8479 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008480 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008481 if(not $Force and $GCC_44
8482 and $OSgroup eq "linux")
8483 { # optimization for linux with GCC >= 4.4
8484 # disable this code by -force option
8485 if(index($CName, "::")!=-1)
8486 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008487 next;
8488 }
8489 }
8490 else
8491 {
8492 if($CName=~/\A(.+)::[^:]+\Z/
8493 and $TUnit_Classes{$Version}{$1})
8494 { # classes inside other classes
8495 next;
8496 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008497 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008498 if(defined $TUnit_Funcs{$Version}{$CName})
8499 { # the same name for a function and type
8500 next;
8501 }
8502 if(defined $TUnit_Vars{$Version}{$CName})
8503 { # the same name for a variable and type
8504 next;
8505 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008506 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8507 }
8508 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008509 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008510 }
8511 }
8512 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8513 # create TU dump
8514 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008515 if($UserLang eq "C") {
8516 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8517 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008518 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008519 or $MinGWMode{$Version}==1) {
8520 $TUdump .= " -fpreprocessed";
8521 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008522 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8524 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008525 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008526 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008527 if($?)
8528 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008529 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008530 { # try to recompile
8531 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008532 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008533 and index($Errors, "c99_")!=-1
8534 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008535 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008536 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008537
8538 if($Debug)
8539 {
8540 # printMsg("INFO", $Errors);
8541 }
8542
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008543 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008544 resetLogging($Version);
8545 $TMP_DIR = tempdir(CLEANUP=>1);
8546 return getDump();
8547 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008548 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008549 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008550 { # add auto preamble headers and try again
8551 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008552 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008553 foreach my $Num (0 .. $#Headers)
8554 {
8555 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008556 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8557 {
8558 push_U($Include_Preamble{$Version}, $Path);
8559 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008560 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008561 }
8562 resetLogging($Version);
8563 $TMP_DIR = tempdir(CLEANUP=>1);
8564 return getDump();
8565 }
8566 elsif($Cpp0xMode{$Version}!=-1
8567 and ($Errors=~/\Q-std=c++0x\E/
8568 or $Errors=~/is not a class or namespace/))
8569 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008570 if(check_gcc($GCC_PATH, "4.6"))
8571 {
8572 $Cpp0xMode{$Version}=-1;
8573 printMsg("INFO", "Enabling c++0x mode");
8574 resetLogging($Version);
8575 $TMP_DIR = tempdir(CLEANUP=>1);
8576 $CompilerOptions{$Version} .= " -std=c++0x";
8577 return getDump();
8578 }
8579 else {
8580 printMsg("WARNING", "Probably c++0x construction detected");
8581 }
8582
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008583 }
8584 elsif($MinGWMode{$Version}==1)
8585 { # disable MinGW mode and try again
8586 $MinGWMode{$Version}=-1;
8587 resetLogging($Version);
8588 $TMP_DIR = tempdir(CLEANUP=>1);
8589 return getDump();
8590 }
8591 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008592 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008593 else {
8594 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008596 printMsg("ERROR", "some errors occurred when compiling headers");
8597 printErrorLog($Version);
8598 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008599 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008600 }
8601 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008602 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008603 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008604
8605 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8606 return $TUs[0];
8607 }
8608 else
8609 {
8610 my $Msg = "can't compile header(s)";
8611 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8612 $Msg .= "\nDid you install G++?";
8613 }
8614 exitStatus("Cannot_Compile", $Msg);
8615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008616}
8617
8618sub cmd_file($)
8619{
8620 my $Path = $_[0];
8621 return "" if(not $Path or not -e $Path);
8622 if(my $CmdPath = get_CmdPath("file")) {
8623 return `$CmdPath -b \"$Path\"`;
8624 }
8625 return "";
8626}
8627
8628sub getIncString($$)
8629{
8630 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008631 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008632 my $String = "";
8633 foreach (@{$ArrRef}) {
8634 $String .= " ".inc_opt($_, $Style);
8635 }
8636 return $String;
8637}
8638
8639sub getIncPaths(@)
8640{
8641 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008642 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008643 if($INC_PATH_AUTODETECT{$Version})
8644 { # auto-detecting dependencies
8645 my %Includes = ();
8646 foreach my $HPath (@HeaderPaths)
8647 {
8648 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8649 {
8650 if($Skip_Include_Paths{$Version}{$Dir}) {
8651 next;
8652 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008653 if($SystemRoot)
8654 {
8655 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8656 next;
8657 }
8658 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008659 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008660 }
8661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008662 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008663 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008664 }
8665 }
8666 else
8667 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008668 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008669 }
8670 return \@IncPaths;
8671}
8672
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008673sub push_U($@)
8674{ # push unique
8675 if(my $Array = shift @_)
8676 {
8677 if(@_)
8678 {
8679 my %Exist = map {$_=>1} @{$Array};
8680 foreach my $Elem (@_)
8681 {
8682 if(not defined $Exist{$Elem})
8683 {
8684 push(@{$Array}, $Elem);
8685 $Exist{$Elem} = 1;
8686 }
8687 }
8688 }
8689 }
8690}
8691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008692sub callPreprocessor($$$)
8693{
8694 my ($Path, $Inc, $LibVersion) = @_;
8695 return "" if(not $Path or not -f $Path);
8696 my $IncludeString=$Inc;
8697 if(not $Inc) {
8698 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8699 }
8700 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008701 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008702 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008703 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008704}
8705
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008706sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008707{ # native "find" is much faster than File::Find (~6x)
8708 # also the File::Find doesn't support --maxdepth N option
8709 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008710 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008711 return () if(not $Path or not -e $Path);
8712 if($OSgroup eq "windows")
8713 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008714 $Path = get_abs_path($Path);
8715 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008716 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008717 if($MaxDepth!=1) {
8718 $Cmd .= " /S";
8719 }
8720 if($Type eq "d") {
8721 $Cmd .= " /AD";
8722 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008723 elsif($Type eq "f") {
8724 $Cmd .= " /A-D";
8725 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008726 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008727 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008728 {
8729 if(not $UseRegex)
8730 { # FIXME: how to search file names in MS shell?
8731 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008732 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008733 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008734 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008735 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008736 }
8737 my @AbsPaths = ();
8738 foreach my $File (@Files)
8739 {
8740 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008741 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008742 }
8743 if($Type eq "f" and not -f $File)
8744 { # skip dirs
8745 next;
8746 }
8747 push(@AbsPaths, path_format($File, $OSgroup));
8748 }
8749 if($Type eq "d") {
8750 push(@AbsPaths, $Path);
8751 }
8752 return @AbsPaths;
8753 }
8754 else
8755 {
8756 my $FindCmd = get_CmdPath("find");
8757 if(not $FindCmd) {
8758 exitStatus("Not_Found", "can't find a \"find\" command");
8759 }
8760 $Path = get_abs_path($Path);
8761 if(-d $Path and -l $Path
8762 and $Path!~/\/\Z/)
8763 { # for directories that are symlinks
8764 $Path.="/";
8765 }
8766 my $Cmd = $FindCmd." \"$Path\"";
8767 if($MaxDepth) {
8768 $Cmd .= " -maxdepth $MaxDepth";
8769 }
8770 if($Type) {
8771 $Cmd .= " -type $Type";
8772 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008773 if($Name and not $UseRegex)
8774 { # wildcards
8775 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008776 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008777 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008778 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008779 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8780 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008781 my @Files = split(/\n/, $Res);
8782 if($Name and $UseRegex)
8783 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008784 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008785 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008786 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008787 }
8788}
8789
8790sub unpackDump($)
8791{
8792 my $Path = $_[0];
8793 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008794
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008795 $Path = get_abs_path($Path);
8796 $Path = path_format($Path, $OSgroup);
8797 my ($Dir, $FileName) = separate_path($Path);
8798 my $UnpackDir = $TMP_DIR."/unpack";
8799 rmtree($UnpackDir);
8800 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008802 if($FileName=~s/\Q.zip\E\Z//g)
8803 { # *.zip
8804 my $UnzipCmd = get_CmdPath("unzip");
8805 if(not $UnzipCmd) {
8806 exitStatus("Not_Found", "can't find \"unzip\" command");
8807 }
8808 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008809 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008811 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008812 }
8813 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008814 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008815 if(not @Contents) {
8816 exitStatus("Error", "can't extract \'$Path\'");
8817 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008818 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008819 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008820 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008821 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008822 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008823 if($OSgroup eq "windows")
8824 { # -xvzf option is not implemented in tar.exe (2003)
8825 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8826 my $TarCmd = get_CmdPath("tar");
8827 if(not $TarCmd) {
8828 exitStatus("Not_Found", "can't find \"tar\" command");
8829 }
8830 my $GzipCmd = get_CmdPath("gzip");
8831 if(not $GzipCmd) {
8832 exitStatus("Not_Found", "can't find \"gzip\" command");
8833 }
8834 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008835 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008836 if($?) {
8837 exitStatus("Error", "can't extract \'$Path\'");
8838 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008839 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008841 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008842 }
8843 chdir($ORIG_DIR);
8844 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008845 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008846 if(not @Contents) {
8847 exitStatus("Error", "can't extract \'$Path\'");
8848 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008849 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 }
8851 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008852 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 my $TarCmd = get_CmdPath("tar");
8854 if(not $TarCmd) {
8855 exitStatus("Not_Found", "can't find \"tar\" command");
8856 }
8857 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008858 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008859 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008860 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008861 }
8862 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008863 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864 if(not @Contents) {
8865 exitStatus("Error", "can't extract \'$Path\'");
8866 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008867 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008868 }
8869 }
8870}
8871
8872sub createArchive($$)
8873{
8874 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008875 if(not $To) {
8876 $To = ".";
8877 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008878 if(not $Path or not -e $Path
8879 or not -d $To) {
8880 return "";
8881 }
8882 my ($From, $Name) = separate_path($Path);
8883 if($OSgroup eq "windows")
8884 { # *.zip
8885 my $ZipCmd = get_CmdPath("zip");
8886 if(not $ZipCmd) {
8887 exitStatus("Not_Found", "can't find \"zip\"");
8888 }
8889 my $Pkg = $To."/".$Name.".zip";
8890 unlink($Pkg);
8891 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008892 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008893 if($?)
8894 { # cannot allocate memory (or other problems with "zip")
8895 unlink($Path);
8896 exitStatus("Error", "can't pack the ABI dump: ".$!);
8897 }
8898 chdir($ORIG_DIR);
8899 unlink($Path);
8900 return $Pkg;
8901 }
8902 else
8903 { # *.tar.gz
8904 my $TarCmd = get_CmdPath("tar");
8905 if(not $TarCmd) {
8906 exitStatus("Not_Found", "can't find \"tar\"");
8907 }
8908 my $GzipCmd = get_CmdPath("gzip");
8909 if(not $GzipCmd) {
8910 exitStatus("Not_Found", "can't find \"gzip\"");
8911 }
8912 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8913 unlink($Pkg);
8914 chdir($From);
8915 system($TarCmd, "-czf", $Pkg, $Name);
8916 if($?)
8917 { # cannot allocate memory (or other problems with "tar")
8918 unlink($Path);
8919 exitStatus("Error", "can't pack the ABI dump: ".$!);
8920 }
8921 chdir($ORIG_DIR);
8922 unlink($Path);
8923 return $To."/".$Name.".tar.gz";
8924 }
8925}
8926
8927sub is_header_file($)
8928{
8929 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8930 return $_[0];
8931 }
8932 return 0;
8933}
8934
8935sub is_not_header($)
8936{
8937 if($_[0]=~/\.\w+\Z/
8938 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8939 return 1;
8940 }
8941 return 0;
8942}
8943
8944sub is_header($$$)
8945{
8946 my ($Header, $UserDefined, $LibVersion) = @_;
8947 return 0 if(-d $Header);
8948 if(-f $Header) {
8949 $Header = get_abs_path($Header);
8950 }
8951 else
8952 {
8953 if(is_abs($Header))
8954 { # incorrect absolute path
8955 return 0;
8956 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008957 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008958 $Header = $HPath;
8959 }
8960 else
8961 { # can't find header
8962 return 0;
8963 }
8964 }
8965 if($Header=~/\.\w+\Z/)
8966 { # have an extension
8967 return is_header_file($Header);
8968 }
8969 else
8970 {
8971 if($UserDefined==2)
8972 { # specified on the command line
8973 if(cmd_file($Header)!~/HTML|XML/i) {
8974 return $Header;
8975 }
8976 }
8977 elsif($UserDefined)
8978 { # specified in the XML-descriptor
8979 # header file without an extension
8980 return $Header;
8981 }
8982 else
8983 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008984 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008985 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008986 { # !~/HTML|XML|shared|dynamic/i
8987 return $Header;
8988 }
8989 }
8990 }
8991 return 0;
8992}
8993
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008994sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008995{
8996 my $LibVersion = $_[0];
8997 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8998 {
8999 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009000 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009001
9002 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9003 detect_recursive_includes($RegHeader, $LibVersion);
9004 }
9005
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009006 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9007 {
9008 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009009
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009010 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009011 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9012 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009013 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009014 }
9015 }
9016 }
9017}
9018
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009019sub familiarDirs($$)
9020{
9021 my ($D1, $D2) = @_;
9022 if($D1 eq $D2) {
9023 return 1;
9024 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009025
9026 my $U1 = index($D1, "/usr/");
9027 my $U2 = index($D2, "/usr/");
9028
9029 if($U1==0 and $U2!=0) {
9030 return 0;
9031 }
9032
9033 if($U2==0 and $U1!=0) {
9034 return 0;
9035 }
9036
9037 if(index($D2, $D1."/")==0) {
9038 return 1;
9039 }
9040
9041 # /usr/include/DIR
9042 # /home/user/DIR
9043
9044 my $DL = get_depth($D1);
9045
9046 my @Dirs1 = ($D1);
9047 while($DL - get_depth($D1)<=2
9048 and get_depth($D1)>=4
9049 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9050 push(@Dirs1, $D1);
9051 }
9052
9053 my @Dirs2 = ($D2);
9054 while(get_depth($D2)>=4
9055 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9056 push(@Dirs2, $D2);
9057 }
9058
9059 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009060 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009061 foreach my $P2 (@Dirs2)
9062 {
9063
9064 if($P1 eq $P2) {
9065 return 1;
9066 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009067 }
9068 }
9069 return 0;
9070}
9071
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072sub readHeaders($)
9073{
9074 $Version = $_[0];
9075 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9076 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009077 if($Debug)
9078 { # debug mode
9079 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009080 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009081 }
9082 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009083}
9084
9085sub prepareTypes($)
9086{
9087 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009088 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009089 { # support for old ABI dumps
9090 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009091 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009092 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009093 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9094 if($TName=~/\A(\w+)::(\w+)/) {
9095 my ($P1, $P2) = ($1, $2);
9096 if($P1 eq $P2) {
9097 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009098 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009099 else {
9100 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009103 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009104 }
9105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009107 { # support for old ABI dumps
9108 # V < 2.5: array size == "number of elements"
9109 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009110 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009111 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009112 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009113 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009114 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009115 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009116 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009117 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009118 $Size *= $Base{"Size"};
9119 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009120 }
9121 else
9122 { # array[] is a pointer
9123 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009124 }
9125 }
9126 }
9127 }
9128 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009129 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009130 { # support for old ABI dumps
9131 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009132 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009133 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009134 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009135 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009136 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009137 my %Type = get_Type($TypeId, $LibVersion);
9138 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9139 my %Type2 = get_Type($TypeId_2, $V2);
9140 if($Type{"Size"} ne $Type2{"Size"}) {
9141 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009142 }
9143 }
9144 }
9145 }
9146}
9147
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009148sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009149{
9150 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009151
9152 if(not keys(%{$SymbolInfo{$LibVersion}}))
9153 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009154 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009155 {
9156 if($CheckHeadersOnly) {
9157 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9158 }
9159 else {
9160 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9161 }
9162 }
9163 }
9164
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009166 if(not checkDump(1, "2.10")
9167 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009168 { # different formats
9169 $Remangle = 1;
9170 }
9171 if($CheckHeadersOnly)
9172 { # different languages
9173 if($UserLang)
9174 { # --lang=LANG for both versions
9175 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9176 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9177 {
9178 if($UserLang eq "C++")
9179 { # remangle symbols
9180 $Remangle = 1;
9181 }
9182 elsif($UserLang eq "C")
9183 { # remove mangling
9184 $Remangle = -1;
9185 }
9186 }
9187 }
9188 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009189
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009190 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009191 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009192 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009193 { # support for old ABI dumps
9194 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9195 {
9196 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9197 {
9198 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9199 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009200 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009201 if(defined $DVal and $DVal ne "")
9202 {
9203 if($TName eq "char") {
9204 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9205 }
9206 elsif($TName eq "bool") {
9207 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9208 }
9209 }
9210 }
9211 }
9212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009213 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009214 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009215 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9216 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009217 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009218 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9219 # + support for old ABI dumps
9220 next;
9221 }
9222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009223 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009224 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009225 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009226 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009227
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009229 if(not checkDump(1, "2.12")
9230 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009231 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009232 if($ShortName eq "operator>>")
9233 {
9234 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9235 { # corrected mangling of operator>>
9236 $SRemangle = 1;
9237 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009238 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009239 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9240 {
9241 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9242 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9243 { # corrected mangling of const global data
9244 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9245 # and incorrectly mangled by old ACC versions
9246 $SRemangle = 1;
9247 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009248 }
9249 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009250 if(not $CheckHeadersOnly)
9251 { # support for old ABI dumps
9252 if(not checkDump(1, "2.17")
9253 or not checkDump(2, "2.17"))
9254 {
9255 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9256 {
9257 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9258 {
9259 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9260 {
9261 $MnglName = $ShortName;
9262 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9263 }
9264 }
9265 }
9266 }
9267 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009268 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009269 { # support for old ABI dumps: some symbols are not mangled in old dumps
9270 # mangle both sets of symbols (old and new)
9271 # NOTE: remangling all symbols by the same mangler
9272 if($MnglName=~/\A_ZN(V|)K/)
9273 { # mangling may be incorrect on old ABI dumps
9274 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009275 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009276 }
9277 if($MnglName=~/\A_ZN(K|)V/)
9278 { # mangling may be incorrect on old ABI dumps
9279 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009280 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009281 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009282 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9283 or (not $ClassID and $CheckHeadersOnly)
9284 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9285 { # support for old ABI dumps, GCC >= 4.0
9286 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009287 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009288 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009289 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009290 $MangledNames{$LibVersion}{$MnglName} = 1;
9291 }
9292 }
9293 }
9294 elsif($Remangle==-1)
9295 { # remove mangling
9296 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009297 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009299 if(not $MnglName) {
9300 next;
9301 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009302
9303 # NOTE: duplicated entries in the ABI Dump
9304 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9305 {
9306 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9307 {
9308 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9309 {
9310 next;
9311 }
9312 }
9313 }
9314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009315 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9316 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009317 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9318
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009319 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009320 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009321 { # support for old dumps
9322 # add "Volatile" attribute
9323 if($MnglName=~/_Z(K|)V/) {
9324 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9325 }
9326 }
9327 # symbol and its symlink have same signatures
9328 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009329 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009330 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009331
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009332 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9333 {
9334 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009335
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009336 if($SymVer{$LibVersion}{$Alias}) {
9337 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9338 }
9339 }
9340
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009341 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009342 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009343 }
9344 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9345 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9346 }
9347 if($ExtendedCheck)
9348 { # --ext option
9349 addExtension($LibVersion);
9350 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009351
9352 # clean memory
9353 delete($SymbolInfo{$LibVersion});
9354
9355 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009356 { # detect allocable classes with public exported constructors
9357 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009358 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009359 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009360 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009361 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9363 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009364 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009365 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009366 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009367 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009368 $AllocableClass{$LibVersion}{$ClassName} = 1;
9369 }
9370 }
9371 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009372 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009373 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009374 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009375 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009376 if($CheckHeadersOnly)
9377 {
9378 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9379 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9380 { # all symbols except non-virtual inline
9381 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9382 }
9383 }
9384 else {
9385 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 }
9387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009388 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009389 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009390 }
9391 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009392 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009394 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009395 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009396 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009397 if(defined $Base{"Type"}
9398 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009401 if($Name=~/<([^<>\s]+)>/)
9402 {
9403 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9404 $ReturnedClass{$LibVersion}{$Tid} = 1;
9405 }
9406 }
9407 else {
9408 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9409 }
9410 }
9411 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009412 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009413 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009414 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009415 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009417 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009418 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009419 if($Base{"Type"}=~/Struct|Class/)
9420 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009421 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009422 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9423 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009424 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009426 }
9427 }
9428 }
9429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009430
9431 # mapping {short name => symbols}
9432 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009434 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009435 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009436 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009437 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009438 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009439 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009440 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9441 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009442 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009443 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009444 }
9445 }
9446 }
9447 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009448
9449 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009450 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009452 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009454 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9455 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009456 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009457 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009458 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009459 $ClassNames{$LibVersion}{$TName} = 1;
9460 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009461 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009462 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9463 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009464 }
9465 }
9466 }
9467 }
9468 }
9469}
9470
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009471sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009472{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009473 my ($Tid, $LibVersion) = @_;
9474 if(not $Tid) {
9475 return $Tid;
9476 }
9477
9478 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9479 {
9480 if($TName_Tid{$LibVersion}{$Name}) {
9481 return $TName_Tid{$LibVersion}{$Name};
9482 }
9483 }
9484
9485 return $Tid;
9486}
9487
9488sub register_SymbolUsage($$$)
9489{
9490 my ($InfoId, $UsedType, $LibVersion) = @_;
9491
9492 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9493 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9494 {
9495 register_TypeUsage($RTid, $UsedType, $LibVersion);
9496 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9497 }
9498 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9499 {
9500 register_TypeUsage($FCid, $UsedType, $LibVersion);
9501 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9502
9503 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9504 { # register "this" pointer
9505 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9506 }
9507 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9508 { # register "this" pointer (const method)
9509 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9510 }
9511 }
9512 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9513 {
9514 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9515 {
9516 register_TypeUsage($PTid, $UsedType, $LibVersion);
9517 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9518 }
9519 }
9520 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9521 {
9522 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9523 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9524 register_TypeUsage($TTid, $UsedType, $LibVersion);
9525 }
9526 }
9527}
9528
9529sub register_TypeUsage($$$)
9530{
9531 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009532 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009533 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009535 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009536 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009537 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009538 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009539
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009540 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009541 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009542 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009543 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009544 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009545 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9546 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9547 }
9548 }
9549
9550 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9551 {
9552 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009553 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009554 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009555 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9556 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009557 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009558 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9559 {
9560 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9561 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009562 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009563 }
9564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009565 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009566 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009567 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009568 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9569 {
9570 register_TypeUsage($MTid, $UsedType, $LibVersion);
9571 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009572 }
9573 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009574 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009575 or $TInfo{"Type"} eq "MethodPtr"
9576 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009577 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009578 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009579 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009580 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009581 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009582 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009583 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9584 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009585 }
9586 }
9587 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009588 if($TInfo{"Type"} eq "FieldPtr")
9589 {
9590 if(my $RTid = $TInfo{"Return"}) {
9591 register_TypeUsage($RTid, $UsedType, $LibVersion);
9592 }
9593 if(my $CTid = $TInfo{"Class"}) {
9594 register_TypeUsage($CTid, $UsedType, $LibVersion);
9595 }
9596 }
9597 if($TInfo{"Type"} eq "MethodPtr")
9598 {
9599 if(my $CTid = $TInfo{"Class"}) {
9600 register_TypeUsage($CTid, $UsedType, $LibVersion);
9601 }
9602 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009603 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009604 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009605 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009606 $UsedType->{$TypeId} = 1;
9607 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9608 {
9609 register_TypeUsage($BTid, $UsedType, $LibVersion);
9610 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9611 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009612 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009613 else
9614 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9615 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009616 }
9617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009618}
9619
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009620sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009621{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009622 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9623
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009624 if($Level eq "Dump")
9625 {
9626 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9627 { # TODO: check if this symbol is from
9628 # base classes of other target symbols
9629 return 1;
9630 }
9631 }
9632
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009633 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9634 { # stdc++ interfaces
9635 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009636 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009637
9638 my $Target = 0;
9639 if(my $Header = $SInfo->{"Header"}) {
9640 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9641 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009642 if($ExtendedCheck)
9643 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009644 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009645 $Target = 1;
9646 }
9647 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009648 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009649 {
9650 if($Target)
9651 {
9652 if($Level eq "Dump")
9653 { # dumped
9654 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009655 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009656 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009657 return 1;
9658 }
9659 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009660 else {
9661 return 1;
9662 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009664 elsif($Level eq "Source")
9665 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009666 return 1;
9667 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009668 elsif($Level eq "Binary")
9669 { # checked
9670 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9671 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9672 return 1;
9673 }
9674 }
9675 }
9676 }
9677 else
9678 { # library is available
9679 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9680 { # exported symbols
9681 return 1;
9682 }
9683 if($Level eq "Dump")
9684 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009685 if($BinaryOnly)
9686 {
9687 if($SInfo->{"Data"})
9688 {
9689 if($Target) {
9690 return 1;
9691 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009692 }
9693 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009694 else
9695 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009696 if($Target) {
9697 return 1;
9698 }
9699 }
9700 }
9701 elsif($Level eq "Source")
9702 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009703 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009704 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009705 { # skip LOCAL symbols
9706 if($Target) {
9707 return 1;
9708 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009709 }
9710 }
9711 elsif($Level eq "Binary")
9712 { # checked
9713 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9714 {
9715 if($Target) {
9716 return 1;
9717 }
9718 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009719 }
9720 }
9721 return 0;
9722}
9723
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009724sub cleanDump($)
9725{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009726 my $LibVersion = $_[0];
9727 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9728 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009729 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9730 {
9731 delete($SymbolInfo{$LibVersion}{$InfoId});
9732 next;
9733 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009734 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009735 if(not $MnglName)
9736 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009737 delete($SymbolInfo{$LibVersion}{$InfoId});
9738 next;
9739 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009740 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009741 if(not $ShortName)
9742 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009743 delete($SymbolInfo{$LibVersion}{$InfoId});
9744 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009745 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009746 if($MnglName eq $ShortName)
9747 { # remove duplicate data
9748 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009749 }
9750 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9751 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9752 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009753 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9754 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9755 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009756 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009757 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009758 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009759 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009760 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9761 {
9762 delete($TypeInfo{$LibVersion}{$Tid});
9763 next;
9764 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009765 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009766 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009767 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009768 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9769 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9770 }
9771 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009772 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9773 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9774 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009775 }
9776}
9777
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009778sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009779{
9780 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009781
9782 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9783 {
9784 if(defined $TypeInfo{$LibVersion}{$Dupl})
9785 {
9786 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9787 { # duplicate
9788 return 0;
9789 }
9790 }
9791 }
9792
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009793 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9794
9795 if(isBuiltIn($THeader)) {
9796 return 0;
9797 }
9798
9799 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9800 return 0;
9801 }
9802
9803 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9804 return 0;
9805 }
9806
9807 if(selfTypedef($Tid, $LibVersion)) {
9808 return 0;
9809 }
9810
9811 if(not isTargetType($Tid, $LibVersion)) {
9812 return 0;
9813 }
9814
9815 return 0;
9816}
9817
9818sub isTargetType($$)
9819{
9820 my ($Tid, $LibVersion) = @_;
9821
9822 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9823 { # derived
9824 return 1;
9825 }
9826
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009827 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009828 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009829 if(not is_target_header($THeader, $LibVersion))
9830 { # from target headers
9831 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009832 }
9833 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009834 else
9835 { # NOTE: if type is defined in source
9836 if($UsedDump{$LibVersion}{"Public"})
9837 {
9838 if(isPrivateABI($Tid, $LibVersion)) {
9839 return 0;
9840 }
9841 else {
9842 return 1;
9843 }
9844 }
9845 else {
9846 return 0;
9847 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009848 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009849
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009850 if($SkipInternalTypes)
9851 {
9852 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9853 {
9854 return 0;
9855 }
9856 }
9857
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009858 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009859}
9860
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009861sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009862{ # remove unused data types from the ABI dump
9863 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009864
9865 my %UsedType = ();
9866
9867 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009868 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009869 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009870 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009871 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009872 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009873 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009874 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009875 next;
9876 }
9877
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009878 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009879 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009880 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009881 {
9882 my %Tree = ();
9883 register_TypeUsage($Tid, \%Tree, $LibVersion);
9884
9885 my $Tmpl = 0;
9886 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9887 {
9888 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9889 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9890 {
9891 $Tmpl = 1;
9892 last;
9893 }
9894 }
9895 if(not $Tmpl)
9896 {
9897 foreach (keys(%Tree)) {
9898 $UsedType{$_} = 1;
9899 }
9900 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009901 }
9902 }
9903 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009904
9905 my %Delete = ();
9906
9907 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009908 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009909 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009910 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009911 next;
9912 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009913
9914 if($Kind eq "Extra")
9915 {
9916 my %Tree = ();
9917 register_TypeUsage($Tid, \%Tree, $LibVersion);
9918
9919 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9920 {
9921 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9922 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9923 {
9924 $Delete{$Tid} = 1;
9925 last;
9926 }
9927 }
9928 }
9929 else
9930 {
9931 # remove type
9932 delete($TypeInfo{$LibVersion}{$Tid});
9933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009934 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009935
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009936 if($Kind eq "Extra")
9937 { # remove duplicates
9938 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9939 {
9940 if($UsedType{$Tid})
9941 { # All & Extended
9942 next;
9943 }
9944
9945 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9946
9947 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9948 delete($TypeInfo{$LibVersion}{$Tid});
9949 }
9950 }
9951 }
9952
9953 foreach my $Tid (keys(%Delete))
9954 {
9955 delete($TypeInfo{$LibVersion}{$Tid});
9956 }
9957}
9958
9959sub check_Completeness($$)
9960{
9961 my ($Info, $LibVersion) = @_;
9962
9963 # data types
9964 if(defined $Info->{"Memb"})
9965 {
9966 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9967 {
9968 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9969 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9970 }
9971 }
9972 }
9973 if(defined $Info->{"Base"})
9974 {
9975 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9976 check_TypeInfo($Bid, $LibVersion);
9977 }
9978 }
9979 if(defined $Info->{"BaseType"}) {
9980 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9981 }
9982 if(defined $Info->{"TParam"})
9983 {
9984 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9985 {
9986 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9987 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9988 next;
9989 }
9990 if($TName eq "_BoolType") {
9991 next;
9992 }
9993 if($TName=~/\Asizeof\(/) {
9994 next;
9995 }
9996 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9997 check_TypeInfo($Tid, $LibVersion);
9998 }
9999 else
10000 {
10001 if(defined $Debug) {
10002 printMsg("WARNING", "missed type $TName");
10003 }
10004 }
10005 }
10006 }
10007
10008 # symbols
10009 if(defined $Info->{"Param"})
10010 {
10011 foreach my $Pos (keys(%{$Info->{"Param"}}))
10012 {
10013 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10014 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10015 }
10016 }
10017 }
10018 if(defined $Info->{"Return"}) {
10019 check_TypeInfo($Info->{"Return"}, $LibVersion);
10020 }
10021 if(defined $Info->{"Class"}) {
10022 check_TypeInfo($Info->{"Class"}, $LibVersion);
10023 }
10024}
10025
10026sub check_TypeInfo($$)
10027{
10028 my ($Tid, $LibVersion) = @_;
10029
10030 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10031 return;
10032 }
10033 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10034
10035 if(defined $TypeInfo{$LibVersion}{$Tid})
10036 {
10037 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10038 printMsg("ERROR", "missed type name ($Tid)");
10039 }
10040 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10041 }
10042 else {
10043 printMsg("ERROR", "missed type id $Tid");
10044 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010045}
10046
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010047sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010048{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010049 my ($TypeId, $LibVersion) = @_;
10050 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010051 if($Type{"Type"} eq "Typedef")
10052 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010053 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010054 if($Base{"Type"}=~/Class|Struct/)
10055 {
10056 if($Type{"Name"} eq $Base{"Name"}) {
10057 return 1;
10058 }
10059 elsif($Type{"Name"}=~/::(\w+)\Z/)
10060 {
10061 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10062 { # QPointer<QWidget>::QPointer
10063 return 1;
10064 }
10065 }
10066 }
10067 }
10068 return 0;
10069}
10070
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010071sub addExtension($)
10072{
10073 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010074 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010075 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010076 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010077 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010078 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10079 $TName=~s/\A(struct|union|class|enum) //;
10080 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010081
10082 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10083 "Header" => "extended.h",
10084 "ShortName" => $Symbol,
10085 "MnglName" => $Symbol,
10086 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10087 );
10088
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010089 $ExtendedSymbols{$Symbol} = 1;
10090 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10091 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010092 }
10093 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010094 $ExtendedSymbols{"external_func_0"} = 1;
10095 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10096 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010097}
10098
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010099sub findMethod($$$)
10100{
10101 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010102 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010103 {
10104 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10105 return $VirtMethodInClass;
10106 }
10107 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10108 return $VirtMethodInBaseClasses;
10109 }
10110 }
10111 return "";
10112}
10113
10114sub findMethod_Class($$$)
10115{
10116 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010117 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010118 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10119 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10120 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10121 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10122 { # search for interface with the same parameters suffix (overridden)
10123 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10124 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010125 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10126 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010127 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10128 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010129 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10130 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10131 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10132 return $Candidate;
10133 }
10134 }
10135 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010136 else
10137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010138 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10139 return $Candidate;
10140 }
10141 }
10142 }
10143 }
10144 return "";
10145}
10146
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010147sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010148{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010149 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010150 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010151 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010152 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10153 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010155 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010157 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10158 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 { # pure virtual D2-destructors are marked as "virt" in the dump
10160 # virtual D2-destructors are NOT marked as "virt" in the dump
10161 # both destructors are not presented in the v-table
10162 next;
10163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010164 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010167 }
10168}
10169
10170sub registerOverriding($)
10171{
10172 my $LibVersion = $_[0];
10173 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010174 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010175 foreach my $ClassName (@Classes)
10176 {
10177 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10178 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010179 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10180 { # pure virtuals
10181 next;
10182 }
10183 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10184 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010185 {
10186 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10187 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10188 { # both overridden virtual methods
10189 # and implemented pure virtual methods
10190 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10191 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10192 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010194 }
10195 }
10196 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10197 delete($VirtualTable{$LibVersion}{$ClassName});
10198 }
10199 }
10200}
10201
10202sub setVirtFuncPositions($)
10203{
10204 my $LibVersion = $_[0];
10205 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10206 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010207 my ($Num, $Rel) = (1, 0);
10208
10209 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010210 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010211 if($UsedDump{$LibVersion}{"DWARF"}) {
10212 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10213 }
10214 else {
10215 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10216 }
10217 foreach my $VirtFunc (@Funcs)
10218 {
10219 if($UsedDump{$LibVersion}{"DWARF"}) {
10220 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10221 }
10222 else {
10223 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10224 }
10225
10226 # set relative positions
10227 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10228 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10229 { # relative position excluding added and removed virtual functions
10230 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10231 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10232 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 }
10237 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010238 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010239 {
10240 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010241 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010242 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010243 }
10244 }
10245}
10246
10247sub get_sub_classes($$$)
10248{
10249 my ($ClassId, $LibVersion, $Recursive) = @_;
10250 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10251 my @Subs = ();
10252 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10253 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010254 if($Recursive)
10255 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10257 push(@Subs, $SubSubId);
10258 }
10259 }
10260 push(@Subs, $SubId);
10261 }
10262 return @Subs;
10263}
10264
10265sub get_base_classes($$$)
10266{
10267 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010268 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010269 return () if(not defined $ClassType{"Base"});
10270 my @Bases = ();
10271 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10272 keys(%{$ClassType{"Base"}}))
10273 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010274 if($Recursive)
10275 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010276 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10277 push(@Bases, $SubBaseId);
10278 }
10279 }
10280 push(@Bases, $BaseId);
10281 }
10282 return @Bases;
10283}
10284
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010285sub getVTable_Model($$)
10286{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 my ($ClassId, $LibVersion) = @_;
10288 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10289 my @Elements = ();
10290 foreach my $BaseId (@Bases, $ClassId)
10291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010292 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010293 {
10294 if(defined $VirtualTable{$LibVersion}{$BName})
10295 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010296 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10297 if($UsedDump{$LibVersion}{"DWARF"}) {
10298 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10299 }
10300 else {
10301 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10302 }
10303 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010304 push(@Elements, $VFunc);
10305 }
10306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010307 }
10308 }
10309 return @Elements;
10310}
10311
10312sub getVShift($$)
10313{
10314 my ($ClassId, $LibVersion) = @_;
10315 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10316 my $VShift = 0;
10317 foreach my $BaseId (@Bases)
10318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010319 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010320 {
10321 if(defined $VirtualTable{$LibVersion}{$BName}) {
10322 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010324 }
10325 }
10326 return $VShift;
10327}
10328
10329sub getShift($$)
10330{
10331 my ($ClassId, $LibVersion) = @_;
10332 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10333 my $Shift = 0;
10334 foreach my $BaseId (@Bases)
10335 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010336 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010337 {
10338 if($Size!=1)
10339 { # not empty base class
10340 $Shift+=$Size;
10341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 }
10343 }
10344 return $Shift;
10345}
10346
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010347sub getVTable_Size($$)
10348{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010349 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010350 my $Size = 0;
10351 # three approaches
10352 if(not $Size)
10353 { # real size
10354 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10355 $Size = keys(%VTable);
10356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010357 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010358 if(not $Size)
10359 { # shared library symbol size
10360 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10361 $Size /= $WORD_SIZE{$LibVersion};
10362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010363 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010364 if(not $Size)
10365 { # model size
10366 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10367 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10368 }
10369 }
10370 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010371}
10372
10373sub isCopyingClass($$)
10374{
10375 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010376 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010377}
10378
10379sub isLeafClass($$)
10380{
10381 my ($ClassId, $LibVersion) = @_;
10382 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10383}
10384
10385sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010386{ # check structured type for public fields
10387 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388}
10389
10390sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010391{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010392 my ($TypePtr, $Skip, $Start, $End) = @_;
10393 return 0 if(not $TypePtr);
10394 if($End==-1) {
10395 $End = keys(%{$TypePtr->{"Memb"}})-1;
10396 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010397 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010398 {
10399 if($Skip and $Skip->{$MemPos})
10400 { # skip removed/added fields
10401 next;
10402 }
10403 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10404 {
10405 if(isPublic($TypePtr, $MemPos)) {
10406 return ($MemPos+1);
10407 }
10408 }
10409 }
10410 return 0;
10411}
10412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010413sub isReserved($)
10414{ # reserved fields == private
10415 my $MName = $_[0];
10416 if($MName=~/reserved|padding|f_spare/i) {
10417 return 1;
10418 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010419 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010420 return 1;
10421 }
10422 if($MName=~/(pad\d+)/i) {
10423 return 1;
10424 }
10425 return 0;
10426}
10427
10428sub isPublic($$)
10429{
10430 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010431
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432 return 0 if(not $TypePtr);
10433 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10434 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010435
10436 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10437 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010438 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010439 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010440 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010441
10442 # by name in C language
10443 # TODO: add other methods to detect private members
10444 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10445 if($MName=~/priv|abidata|parent_object/i)
10446 { # C-styled private data
10447 return 0;
10448 }
10449 if(lc($MName) eq "abi")
10450 { # ABI information/reserved field
10451 return 0;
10452 }
10453 if(isReserved($MName))
10454 { # reserved fields
10455 return 0;
10456 }
10457
10458 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010459}
10460
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010461sub getVTable_Real($$)
10462{
10463 my ($ClassName, $LibVersion) = @_;
10464 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10465 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010466 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010467 if(defined $Type{"VTable"}) {
10468 return %{$Type{"VTable"}};
10469 }
10470 }
10471 return ();
10472}
10473
10474sub cmpVTables($)
10475{
10476 my $ClassName = $_[0];
10477 my $Res = cmpVTables_Real($ClassName, 1);
10478 if($Res==-1) {
10479 $Res = cmpVTables_Model($ClassName);
10480 }
10481 return $Res;
10482}
10483
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010484sub cmpVTables_Model($)
10485{
10486 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010489 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010490 return 1;
10491 }
10492 }
10493 return 0;
10494}
10495
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010497{
10498 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10500 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010501 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 my %VTable_Old = getVTable_Real($ClassName, 1);
10503 my %VTable_New = getVTable_Real($ClassName, 2);
10504 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010506 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010507 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010508 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010509 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10510 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010511 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010512 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010513 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010514 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010515 my $Entry1 = $VTable_Old{$Offset};
10516 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010519 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010520 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010522 $Entry1 = simpleVEntry($Entry1);
10523 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010524
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010525 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010526 { # NOTE: problem with vtable-dumper
10527 next;
10528 }
10529
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010530 if($Entry1 ne $Entry2)
10531 { # register as changed
10532 if($Entry1=~/::([^:]+)\Z/)
10533 {
10534 my $M1 = $1;
10535 if($Entry2=~/::([^:]+)\Z/)
10536 {
10537 my $M2 = $1;
10538 if($M1 eq $M2)
10539 { # overridden
10540 next;
10541 }
10542 }
10543 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010544 if(differentDumps("G"))
10545 {
10546 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10547 {
10548 # GCC 4.6.1: -0x00000000000000010
10549 # GCC 4.7.0: -16
10550 next;
10551 }
10552 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010553 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010554 }
10555 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010556 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557}
10558
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010559sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010561 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10563 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010564 my $ClassId = $TName_Tid{1}{$ClassName};
10565 if(isPrivateABI($ClassId, 1)) {
10566 next;
10567 }
10568
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 { # already registered
10571 next;
10572 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010575 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 foreach my $Symbol (@Affected)
10577 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010578 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010580 "Target"=>$ClassName);
10581 }
10582 }
10583 }
10584}
10585
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010586sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010588 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010589 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010591 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010592 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010593
10594 if(isPrivateABI($ClassId, 1)) {
10595 next;
10596 }
10597
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010598 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010600 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010601 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010602 if($TName_Tid{1}{$ClassName}
10603 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010604 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010605 if(defined $CompleteSignature{1}{$Symbol}
10606 and $CompleteSignature{1}{$Symbol}{"Virt"})
10607 { # override some method in v.1
10608 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010609 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010610 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010611 }
10612 }
10613 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010614 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010616 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010617 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010618 if($TName_Tid{2}{$ClassName}
10619 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010620 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010621 if(defined $CompleteSignature{2}{$Symbol}
10622 and $CompleteSignature{2}{$Symbol}{"Virt"})
10623 { # override some method in v.2
10624 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010625 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010626 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010627 }
10628 }
10629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010630 if($Level eq "Binary")
10631 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010632 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010633 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10634 { # check replacements, including pure virtual methods
10635 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10636 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010637 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010638 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10639 if($AddedPos==$RemovedPos)
10640 {
10641 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10642 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10643 last; # other methods will be reported as "added" or "removed"
10644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010645 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010646 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10647 {
10648 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10649 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010650 next;
10651 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010652 my $ProblemType = "Virtual_Replacement";
10653 my @Affected = ($RemovedVFunc);
10654 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10655 { # pure methods
10656 if(not isUsedClass($ClassId, 1, $Level))
10657 { # not a parameter of some exported method
10658 next;
10659 }
10660 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010661
10662 # affected all methods (both virtual and non-virtual ones)
10663 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10664 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010666 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010667 foreach my $AffectedInt (@Affected)
10668 {
10669 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10670 { # affected exported methods only
10671 next;
10672 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010673 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10674 next;
10675 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010676 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10677 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010678 "Target"=>get_Signature($AddedVFunc, 2),
10679 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681 }
10682 }
10683 }
10684 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010685 if(not checkDump(1, "2.0")
10686 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010687 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010688 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010689 return;
10690 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010691 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010693 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010694 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010695
10696 if(isPrivateABI($ClassId_Old, 1)) {
10697 next;
10698 }
10699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010700 if(not isCreatable($ClassId_Old, 1))
10701 { # skip classes without public constructors (including auto-generated)
10702 # example: class has only a private exported or private inline constructor
10703 next;
10704 }
10705 if($ClassName=~/>/)
10706 { # skip affected template instances
10707 next;
10708 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010709 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010710 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010711 if(not $ClassId_New) {
10712 next;
10713 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010714 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010715 if($Class_New{"Type"}!~/Class|Struct/)
10716 { # became typedef
10717 if($Level eq "Binary") {
10718 next;
10719 }
10720 if($Level eq "Source")
10721 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010722 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010723 if($Class_New{"Type"}!~/Class|Struct/) {
10724 next;
10725 }
10726 $ClassId_New = $Class_New{"Tid"};
10727 }
10728 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010729
10730 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10731 { # incomplete info in the ABI dump
10732 next;
10733 }
10734
10735
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010736 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10737 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 +040010738
10739 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10740 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10741
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010743 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10744 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010745 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10746 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010747 my $Shift_Old = getShift($ClassId_Old, 1);
10748 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010749 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010750 my ($Added, $Removed) = (0, 0);
10751 my @StableBases_Old = ();
10752 foreach my $BaseId (@Bases_Old)
10753 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010754 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010755 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010756 push(@StableBases_Old, $BaseId);
10757 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010758 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010759 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 { # removed base
10761 # excluding namespace::SomeClass to SomeClass renaming
10762 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010763 if($Level eq "Binary")
10764 { # Binary-level
10765 if($Shift_Old ne $Shift_New)
10766 { # affected fields
10767 if(havePubFields(\%Class_Old)) {
10768 $ProblemKind .= "_And_Shift";
10769 }
10770 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10771 $ProblemKind .= "_And_Size";
10772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010773 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010774 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10775 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010776 { # affected v-table
10777 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010778 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010779 }
10780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010781 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010782 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10783 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010784 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10785 {
10786 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10787 if($ProblemKind=~/VTable/) {
10788 $VTableChanged_M{$SubName}=1;
10789 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010790 }
10791 }
10792 foreach my $Interface (@Affected)
10793 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010794 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10795 next;
10796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010797 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010799 "Target"=>$BaseName,
10800 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10801 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10802 "Shift"=>abs($Shift_New-$Shift_Old) );
10803 }
10804 $Removed+=1;
10805 }
10806 }
10807 my @StableBases_New = ();
10808 foreach my $BaseId (@Bases_New)
10809 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010810 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010811 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010812 push(@StableBases_New, $BaseId);
10813 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010814 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010815 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010816 { # added base
10817 # excluding namespace::SomeClass to SomeClass renaming
10818 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010819 if($Level eq "Binary")
10820 { # Binary-level
10821 if($Shift_Old ne $Shift_New)
10822 { # affected fields
10823 if(havePubFields(\%Class_Old)) {
10824 $ProblemKind .= "_And_Shift";
10825 }
10826 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10827 $ProblemKind .= "_And_Size";
10828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010829 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010830 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10831 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010832 { # affected v-table
10833 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010834 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010835 }
10836 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010837 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010838 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10839 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010840 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10841 {
10842 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10843 if($ProblemKind=~/VTable/) {
10844 $VTableChanged_M{$SubName}=1;
10845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010846 }
10847 }
10848 foreach my $Interface (@Affected)
10849 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010850 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10851 next;
10852 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010854 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010855 "Target"=>$BaseName,
10856 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10857 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10858 "Shift"=>abs($Shift_New-$Shift_Old) );
10859 }
10860 $Added+=1;
10861 }
10862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010863 if($Level eq "Binary")
10864 { # Binary-level
10865 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010866 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10867 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010868 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010869 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010870 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010871 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010872 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010873 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10874 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 if($NewPos!=$OldPos)
10876 { # changed position of the base class
10877 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010878 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010879 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10880 next;
10881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010882 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10883 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010884 "Target"=>$BaseName,
10885 "Old_Value"=>$OldPos-1,
10886 "New_Value"=>$NewPos-1 );
10887 }
10888 }
10889 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10890 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10891 { # became non-virtual base
10892 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10893 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010894 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10895 next;
10896 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010897 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10898 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010899 "Target"=>$BaseName );
10900 }
10901 }
10902 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10903 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10904 { # became virtual base
10905 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10906 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010907 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10908 next;
10909 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010910 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10911 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010912 "Target"=>$BaseName );
10913 }
10914 }
10915 }
10916 }
10917 # detect size changes in base classes
10918 if($Shift_Old!=$Shift_New)
10919 { # size of allocable class
10920 foreach my $BaseId (@StableBases_Old)
10921 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010922 my %BaseType = get_Type($BaseId, 1);
10923 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010924 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010925 if($Size_Old ne $Size_New
10926 and $Size_Old and $Size_New)
10927 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010928 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010929 if(isCopyingClass($BaseId, 1)) {
10930 $ProblemType = "Size_Of_Copying_Class";
10931 }
10932 elsif($AllocableClass{1}{$BaseType{"Name"}})
10933 {
10934 if($Size_New>$Size_Old)
10935 { # increased size
10936 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010938 else
10939 { # decreased size
10940 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10941 if(not havePubFields(\%Class_Old))
10942 { # affected class has no public members
10943 next;
10944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010946 }
10947 next if(not $ProblemType);
10948 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10949 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010950 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10951 next;
10952 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010953 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10954 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010955 "Target"=>$BaseType{"Name"},
10956 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10957 "New_Size"=>$Size_New*$BYTE_SIZE );
10958 }
10959 }
10960 }
10961 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010962 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010963 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010964 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010965 { # compare virtual tables size in base classes
10966 my $VShift_Old = getVShift($ClassId_Old, 1);
10967 my $VShift_New = getVShift($ClassId_New, 2);
10968 if($VShift_Old ne $VShift_New)
10969 { # changes in the base class or changes in the list of base classes
10970 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10971 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10972 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010973 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 foreach my $BaseId (@AllBases_Old)
10975 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010976 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010977 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010978 { # lost base
10979 next;
10980 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010981 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10982 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 if($VSize_Old!=$VSize_New)
10984 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010985 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010986 { # TODO: affected non-virtual methods?
10987 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010988 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10989 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010990 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010991 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010992 { # skip interfaces that have not changed the absolute virtual position
10993 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010994 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010995 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10996 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010998 $VTableChanged_M{$BaseType{"Name"}} = 1;
10999 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011000 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11001 { # the reason of the layout change: added virtual functions
11002 next if($VirtualReplacement{$VirtFunc});
11003 my $ProblemType = "Added_Virtual_Method";
11004 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11005 $ProblemType = "Added_Pure_Virtual_Method";
11006 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011007 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011008 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011009 "Target"=>get_Signature($VirtFunc, 2) );
11010 }
11011 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11012 { # the reason of the layout change: removed virtual functions
11013 next if($VirtualReplacement{$VirtFunc});
11014 my $ProblemType = "Removed_Virtual_Method";
11015 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11016 $ProblemType = "Removed_Pure_Virtual_Method";
11017 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011018 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011019 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011020 "Target"=>get_Signature($VirtFunc, 1) );
11021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011022 }
11023 }
11024 }
11025 }
11026 }
11027 }
11028 }
11029}
11030
11031sub isCreatable($$)
11032{
11033 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011034 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011035 or isCopyingClass($ClassId, $LibVersion)) {
11036 return 1;
11037 }
11038 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11039 { # Fix for incomplete data: if this class has
11040 # a base class then it should also has a constructor
11041 return 1;
11042 }
11043 if($ReturnedClass{$LibVersion}{$ClassId})
11044 { # returned by some method of this class
11045 # or any other class
11046 return 1;
11047 }
11048 return 0;
11049}
11050
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011051sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011052{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011053 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011054 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11055 { # parameter of some exported method
11056 return 1;
11057 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011058 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11059 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011060 { # method from target class
11061 return 1;
11062 }
11063 return 0;
11064}
11065
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011066sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011068 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011069 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011070 # - virtual
11071 # - pure-virtual
11072 # - non-virtual
11073 if($CompleteSignature{1}{$Interface}{"Data"})
11074 { # global data is not affected
11075 return;
11076 }
11077 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011078 if(not $Class_Id) {
11079 return;
11080 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011081 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011082 if(cmpVTables_Real($CName, 1)==0)
11083 { # no changes
11084 return;
11085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 $CheckedTypes{$Level}{$CName} = 1;
11087 if($Level eq "Binary")
11088 { # Binary-level
11089 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11090 and not isUsedClass($Class_Id, 1, $Level))
11091 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011092 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011093 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011094 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011095 }
11096 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11097 {
11098 if(defined $VirtualTable{2}{$CName}{$Func}
11099 and defined $CompleteSignature{2}{$Func})
11100 {
11101 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11102 and $CompleteSignature{2}{$Func}{"PureVirt"})
11103 { # became pure virtual
11104 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11105 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011106 "Target"=>get_Signature_M($Func, 1) );
11107 $VTableChanged_M{$CName} = 1;
11108 }
11109 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11110 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11111 { # became non-pure virtual
11112 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11113 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011114 "Target"=>get_Signature_M($Func, 1) );
11115 $VTableChanged_M{$CName} = 1;
11116 }
11117 }
11118 }
11119 if($Level eq "Binary")
11120 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011121 # check virtual table structure
11122 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11123 {
11124 next if($Interface eq $AddedVFunc);
11125 next if($VirtualReplacement{$AddedVFunc});
11126 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11127 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11128 { # pure virtual methods affect all others (virtual and non-virtual)
11129 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011130 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011132 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011133 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011134 elsif(not defined $VirtualTable{1}{$CName}
11135 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011136 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011137 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011138 { # became polymorphous class, added v-table pointer
11139 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011140 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011141 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011142 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 }
11144 else
11145 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 my $VSize_Old = getVTable_Size($CName, 1);
11147 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011148 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011149 if(isCopyingClass($Class_Id, 1))
11150 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11151 my $ProblemType = "Added_Virtual_Method";
11152 if(isLeafClass($Class_Id, 1)) {
11153 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11154 }
11155 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11156 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011157 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011158 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011159 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 else
11161 {
11162 my $ProblemType = "Added_Virtual_Method";
11163 if(isLeafClass($Class_Id, 1)) {
11164 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11165 }
11166 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11167 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011168 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011169 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011171 }
11172 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11174 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011175 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011176 if(defined $VirtualTable{1}{$CName}
11177 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011178 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011179 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11180 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011181
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011182 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011183 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011184 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11185 foreach my $ASymbol (@Affected)
11186 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011187 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11188 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011189 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011190 next;
11191 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011192 }
11193 $CheckedSymbols{$Level}{$ASymbol} = 1;
11194 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11195 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011196 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011197 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011200 }
11201 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011202 else {
11203 # safe
11204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011205 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011206 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11207 {
11208 next if($VirtualReplacement{$RemovedVFunc});
11209 if($RemovedVFunc eq $Interface
11210 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11211 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011212 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 next;
11214 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011215 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 { # became non-polymorphous class, removed v-table pointer
11217 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11218 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011219 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011220 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011221 }
11222 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11223 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11224 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011225 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011227 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11228 next;
11229 }
11230 my $VPos_New = -1;
11231 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011232 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011233 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11234 }
11235 else
11236 {
11237 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011238 next;
11239 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011240 }
11241 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11242 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11243 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11244 {
11245 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11246 foreach my $ASymbol (@Affected)
11247 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011248 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11249 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011250 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011251 next;
11252 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 }
11254 my $ProblemType = "Removed_Virtual_Method";
11255 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11256 $ProblemType = "Removed_Pure_Virtual_Method";
11257 }
11258 $CheckedSymbols{$Level}{$ASymbol} = 1;
11259 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11260 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011261 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011262 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011263 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011264 }
11265 }
11266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011267 }
11268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011269 else
11270 { # Source-level
11271 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011272 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011273 next if($Interface eq $AddedVFunc);
11274 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011275 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011276 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11277 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011278 "Target"=>get_Signature($AddedVFunc, 2) );
11279 }
11280 }
11281 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11282 {
11283 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11284 {
11285 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11286 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011287 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011288 }
11289 }
11290 }
11291}
11292
11293sub find_MemberPair_Pos_byName($$)
11294{
11295 my ($Member_Name, $Pair_Type) = @_;
11296 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11297 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11298 {
11299 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11300 {
11301 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11302 $Name=~s/\A[_]+|[_]+\Z//g;
11303 if($Name eq $Member_Name) {
11304 return $MemberPair_Pos;
11305 }
11306 }
11307 }
11308 return "lost";
11309}
11310
11311sub find_MemberPair_Pos_byVal($$)
11312{
11313 my ($Member_Value, $Pair_Type) = @_;
11314 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11315 {
11316 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11317 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11318 return $MemberPair_Pos;
11319 }
11320 }
11321 return "lost";
11322}
11323
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011324sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011325{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011326 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011327 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011328 if( $_->{"T1"} eq $_[0]
11329 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011330 {
11331 return 1;
11332 }
11333 }
11334 return 0;
11335}
11336
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011337sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011338{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011339 my %IDs = (
11340 "T1" => $_[0],
11341 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011342 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011343 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344}
11345
11346sub isRenamed($$$$$)
11347{
11348 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11349 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11350 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011351 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 if(not defined $Type2->{"Memb"}{$MemPos}) {
11353 return "";
11354 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011355 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011356 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011358 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11359 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011360 if($MemberPair_Pos_Rev eq "lost")
11361 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011362 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11363 { # base type match
11364 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011366 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11367 { # exact type match
11368 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011370 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11371 { # size match
11372 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011373 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011374 if(isReserved($Pair_Name))
11375 { # reserved fields
11376 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011377 }
11378 }
11379 return "";
11380}
11381
11382sub isLastElem($$)
11383{
11384 my ($Pos, $TypeRef) = @_;
11385 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11386 if($Name=~/last|count|max|total/i)
11387 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11388 return 1;
11389 }
11390 elsif($Name=~/END|NLIMITS\Z/)
11391 { # __RLIMIT_NLIMITS
11392 return 1;
11393 }
11394 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11395 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11396 { # NImageFormats, NColorRoles
11397 return 1;
11398 }
11399 return 0;
11400}
11401
11402sub nonComparable($$)
11403{
11404 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011405
11406 my $N1 = $T1->{"Name"};
11407 my $N2 = $T2->{"Name"};
11408
11409 $N1=~s/\A(struct|union|enum) //;
11410 $N2=~s/\A(struct|union|enum) //;
11411
11412 if($N1 ne $N2
11413 and not isAnon($N1)
11414 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415 { # different names
11416 if($T1->{"Type"} ne "Pointer"
11417 or $T2->{"Type"} ne "Pointer")
11418 { # compare base types
11419 return 1;
11420 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011421 if($N1!~/\Avoid\s*\*/
11422 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011423 {
11424 return 1;
11425 }
11426 }
11427 elsif($T1->{"Type"} ne $T2->{"Type"})
11428 { # different types
11429 if($T1->{"Type"} eq "Class"
11430 and $T2->{"Type"} eq "Struct")
11431 { # "class" to "struct"
11432 return 0;
11433 }
11434 elsif($T2->{"Type"} eq "Class"
11435 and $T1->{"Type"} eq "Struct")
11436 { # "struct" to "class"
11437 return 0;
11438 }
11439 else
11440 { # "class" to "enum"
11441 # "union" to "class"
11442 # ...
11443 return 1;
11444 }
11445 }
11446 return 0;
11447}
11448
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011449sub isOpaque($)
11450{
11451 my $T = $_[0];
11452 if(not defined $T->{"Memb"})
11453 {
11454 return 1;
11455 }
11456 return 0;
11457}
11458
11459sub removeVPtr($)
11460{ # support for old ABI dumps
11461 my $TPtr = $_[0];
11462 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11463 if($#Pos>=1)
11464 {
11465 foreach my $Pos (0 .. $#Pos-1)
11466 {
11467 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11468 }
11469 delete($TPtr->{"Memb"}{$#Pos});
11470 }
11471}
11472
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011473sub isPrivateABI($$)
11474{
11475 my ($TypeId, $LibVersion) = @_;
11476
11477 if($CheckPrivateABI) {
11478 return 0;
11479 }
11480
11481 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11482 return 1;
11483 }
11484
11485 return 0;
11486}
11487
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011488sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011489{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011490 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011491 return {} if(not $Type1_Id or not $Type2_Id);
11492
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011493 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011494 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011495 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011496 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011497
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011498 my %Type1 = get_Type($Type1_Id, 1);
11499 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011500 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011501 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011502 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011503
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011504 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11505 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011506
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011507 if(defined $UsedDump{1}{"DWARF"})
11508 {
11509 if($Type1_Pure{"Name"} eq "__unknown__"
11510 or $Type2_Pure{"Name"} eq "__unknown__")
11511 { # Error ABI dump
11512 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11513 }
11514 }
11515
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011516 if(isPrivateABI($Type1_Id, 1)) {
11517 return {};
11518 }
11519
11520 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11521 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11522
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011523 my %SubProblems = ();
11524
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011525 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11526 {
11527 if($Type1_Pure{"Type"}=~/Struct|Union/
11528 and $Type2_Pure{"Type"}=~/Struct|Union/)
11529 {
11530 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11531 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011532 if(not defined $UsedDump{1}{"DWARF"}
11533 and not defined $UsedDump{2}{"DWARF"})
11534 {
11535 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11536 "Target"=>$Type1_Pure{"Name"},
11537 "Type_Name"=>$Type1_Pure{"Name"} );
11538 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011539
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011540 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011541 }
11542 }
11543 }
11544
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011545 if(not $Type1_Pure{"Size"}
11546 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011547 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011548 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11549 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11550 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011551 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011552 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011553 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011554 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011555 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011556 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011557 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011558 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11559 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11560 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011561
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011562 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11563 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011564 }
11565
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011566 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11567 { # support for old ABI dumps
11568 # _vptr field added in 3.0
11569 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11570 {
11571 if(defined $Type2_Pure{"Memb"}
11572 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11573 {
11574 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11575 delete($Type2_Pure{"Memb"}{0});
11576 }
11577 else {
11578 removeVPtr(\%Type2_Pure);
11579 }
11580 }
11581 }
11582 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11583 {
11584 if(defined $Type1_Pure{"Memb"}
11585 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11586 {
11587 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11588 delete($Type1_Pure{"Memb"}{0});
11589 }
11590 else {
11591 removeVPtr(\%Type1_Pure);
11592 }
11593 }
11594 }
11595 }
11596
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011597 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11598 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011599
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011600 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011601 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11602 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011603 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011604 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11605 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011606 if($Base_1{"Name"} ne $Base_2{"Name"})
11607 {
11608 if(differentDumps("G")
11609 or differentDumps("V"))
11610 { # different GCC versions or different dumps
11611 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11612 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11613 # std::__va_list and __va_list
11614 $Base_1{"Name"}=~s/\A(\w+::)+//;
11615 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011616 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11617 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011619 }
11620 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11621 and $Base_1{"Name"} ne $Base_2{"Name"})
11622 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011623 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011624 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011625 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011626 {
11627 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11628 "Target"=>$Typedef_1{"Name"},
11629 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011630 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11631 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11632 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011633 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11634 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011635
11636 if(defined $UsedDump{1}{"DWARF"})
11637 {
11638 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11639 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11640 { # Error ABI dump
11641 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11642 }
11643 }
11644
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011645 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011646 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011647 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11648 {
11649 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11650 "Target"=>$Typedef_1{"Name"},
11651 "Type_Name"=>$Typedef_1{"Name"},
11652 "Old_Value"=>$Base_1{"Name"},
11653 "New_Value"=>$Base_2{"Name"} );
11654 }
11655 else
11656 {
11657 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11658 "Target"=>$Typedef_1{"Name"},
11659 "Type_Name"=>$Typedef_1{"Name"},
11660 "Old_Value"=>$Base_1{"Name"},
11661 "New_Value"=>$Base_2{"Name"} );
11662 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011664 }
11665 }
11666 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11667 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011668 my $TT1 = $Type1_Pure{"Type"};
11669 my $TT2 = $Type2_Pure{"Type"};
11670
11671 if($TT1 ne $TT2
11672 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011673 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011674 my $Short1 = $Type1_Pure{"Name"};
11675 my $Short2 = $Type2_Pure{"Name"};
11676
11677 $Short1=~s/\A\Q$TT1\E //ig;
11678 $Short2=~s/\A\Q$TT2\E //ig;
11679
11680 if($Short1 eq $Short2)
11681 {
11682 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11683 "Target"=>$Type1_Pure{"Name"},
11684 "Type_Name"=>$Type1_Pure{"Name"},
11685 "Old_Value"=>lc($Type1_Pure{"Type"}),
11686 "New_Value"=>lc($Type2_Pure{"Type"}) );
11687 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011688 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011689 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011690 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011691
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011692 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011693
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11695 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11696 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11697 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011698 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011699 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011700 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011701 {
11702 my $ProblemKind = "DataType_Size";
11703 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011704 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011705 {
11706 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11707 $ProblemKind = "Size_Of_Copying_Class";
11708 }
11709 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11710 {
11711 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11712 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11713 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011714 else
11715 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011716 # descreased size of allocable class
11717 # it has no special effects
11718 }
11719 }
11720 }
11721 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11722 "Target"=>$Type1_Pure{"Name"},
11723 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011724 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011725 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011726 }
11727 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011728 if(defined $Type1_Pure{"BaseType"}
11729 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011730 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011731 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11732 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011734 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11735 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011736 }
11737 }
11738 }
11739 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11740 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11741 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11742 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11743 { # detect removed and renamed fields
11744 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11745 next if(not $Member_Name);
11746 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);
11747 if($MemberPair_Pos eq "lost")
11748 {
11749 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11750 {
11751 if(isUnnamed($Member_Name))
11752 { # support for old-version dumps
11753 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011754 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011755 next;
11756 }
11757 }
11758 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11759 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011760 $RenamedField{$Member_Pos} = $RenamedTo;
11761 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 }
11763 else
11764 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011765 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 }
11767 }
11768 elsif($Type1_Pure{"Type"} eq "Enum")
11769 {
11770 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11771 next if($Member_Value1 eq "");
11772 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11773 if($MemberPair_Pos ne "lost")
11774 { # renamed
11775 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11776 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11777 if($MemberPair_Pos_Rev eq "lost")
11778 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011779 $RenamedField{$Member_Pos} = $RenamedTo;
11780 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011781 }
11782 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011783 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 }
11785 }
11786 else
11787 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011788 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011789 }
11790 }
11791 }
11792 else
11793 { # related
11794 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11795 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11796 }
11797 }
11798 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11799 { # detect added fields
11800 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11801 next if(not $Member_Name);
11802 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);
11803 if($MemberPair_Pos eq "lost")
11804 {
11805 if(isUnnamed($Member_Name))
11806 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011807 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011808 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011809 next;
11810 }
11811 }
11812 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11813 {
11814 if(not $RenamedField_Rev{$Member_Pos})
11815 { # added
11816 $AddedField{$Member_Pos}=1;
11817 }
11818 }
11819 }
11820 }
11821 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11822 { # detect moved fields
11823 my (%RelPos, %RelPosName, %AbsPos) = ();
11824 my $Pos = 0;
11825 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11826 { # relative positions in 1st version
11827 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11828 next if(not $Member_Name);
11829 if(not $RemovedField{$Member_Pos})
11830 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011831 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011832 $RelPosName{1}{$Pos} = $Member_Name;
11833 $AbsPos{1}{$Pos++} = $Member_Pos;
11834 }
11835 }
11836 $Pos = 0;
11837 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11838 { # relative positions in 2nd version
11839 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11840 next if(not $Member_Name);
11841 if(not $AddedField{$Member_Pos})
11842 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011843 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 $RelPosName{2}{$Pos} = $Member_Name;
11845 $AbsPos{2}{$Pos++} = $Member_Pos;
11846 }
11847 }
11848 foreach my $Member_Name (keys(%{$RelPos{1}}))
11849 {
11850 my $RPos1 = $RelPos{1}{$Member_Name};
11851 my $AbsPos1 = $NameToPosA{$Member_Name};
11852 my $Member_Name2 = $Member_Name;
11853 if(my $RenamedTo = $RenamedField{$AbsPos1})
11854 { # renamed
11855 $Member_Name2 = $RenamedTo;
11856 }
11857 my $RPos2 = $RelPos{2}{$Member_Name2};
11858 if($RPos2 ne "" and $RPos1 ne $RPos2)
11859 { # different relative positions
11860 my $AbsPos2 = $NameToPosB{$Member_Name2};
11861 if($AbsPos1 ne $AbsPos2)
11862 { # different absolute positions
11863 my $ProblemType = "Moved_Field";
11864 if(not isPublic(\%Type1_Pure, $AbsPos1))
11865 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011866 if($Level eq "Source") {
11867 next;
11868 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011869 $ProblemType = "Moved_Private_Field";
11870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011871 if($Level eq "Binary"
11872 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011873 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011874 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011875 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011876 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011877 if($MemSize1 ne $MemSize2) {
11878 $ProblemType .= "_And_Size";
11879 }
11880 }
11881 if($ProblemType eq "Moved_Private_Field") {
11882 next;
11883 }
11884 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11885 "Target"=>$Member_Name,
11886 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011887 "Old_Value"=>$RPos1,
11888 "New_Value"=>$RPos2 );
11889 }
11890 }
11891 }
11892 }
11893 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011894 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011895 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11896 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011897 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011898 if(my $RenamedTo = $RenamedField{$Member_Pos})
11899 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011900 if(defined $Constants{2}{$Member_Name})
11901 {
11902 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11903 { # define OLD NEW
11904 next; # Safe
11905 }
11906 }
11907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011908 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11909 {
11910 if(isPublic(\%Type1_Pure, $Member_Pos))
11911 {
11912 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11913 "Target"=>$Member_Name,
11914 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011915 "Old_Value"=>$Member_Name,
11916 "New_Value"=>$RenamedTo );
11917 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011918 elsif(isReserved($Member_Name))
11919 {
11920 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11921 "Target"=>$Member_Name,
11922 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011923 "Old_Value"=>$Member_Name,
11924 "New_Value"=>$RenamedTo );
11925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011926 }
11927 elsif($Type1_Pure{"Type"} eq "Enum")
11928 {
11929 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11930 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11931 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011932 "Old_Value"=>$Member_Name,
11933 "New_Value"=>$RenamedTo );
11934 }
11935 }
11936 elsif($RemovedField{$Member_Pos})
11937 { # removed
11938 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11939 {
11940 my $ProblemType = "Removed_Field";
11941 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011942 or isUnnamed($Member_Name))
11943 {
11944 if($Level eq "Source") {
11945 next;
11946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011947 $ProblemType = "Removed_Private_Field";
11948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011949 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011950 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 {
11952 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11953 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011954 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 { # changed offset
11956 $ProblemType .= "_And_Layout";
11957 }
11958 }
11959 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11960 { # affected size
11961 $ProblemType .= "_And_Size";
11962 }
11963 }
11964 if($ProblemType eq "Removed_Private_Field") {
11965 next;
11966 }
11967 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11968 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011969 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 }
11971 elsif($Type2_Pure{"Type"} eq "Union")
11972 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011973 if($Level eq "Binary"
11974 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011975 {
11976 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11977 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011978 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011979 }
11980 else
11981 {
11982 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11983 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011984 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011985 }
11986 }
11987 elsif($Type1_Pure{"Type"} eq "Enum")
11988 {
11989 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11990 "Target"=>$Member_Name,
11991 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011992 "Old_Value"=>$Member_Name );
11993 }
11994 }
11995 else
11996 { # changed
11997 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11998 if($Type1_Pure{"Type"} eq "Enum")
11999 {
12000 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12001 next if($Member_Value1 eq "");
12002 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12003 next if($Member_Value2 eq "");
12004 if($Member_Value1 ne $Member_Value2)
12005 {
12006 my $ProblemType = "Enum_Member_Value";
12007 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12008 $ProblemType = "Enum_Last_Member_Value";
12009 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012010 if($SkipConstants{1}{$Member_Name}) {
12011 $ProblemType = "Enum_Private_Member_Value";
12012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012013 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12014 "Target"=>$Member_Name,
12015 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012016 "Old_Value"=>$Member_Value1,
12017 "New_Value"=>$Member_Value2 );
12018 }
12019 }
12020 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12021 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012022 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12023 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12024
12025 if($Access1 ne "private"
12026 and $Access2 eq "private")
12027 {
12028 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12029 "Target"=>$Member_Name,
12030 "Type_Name"=>$Type1_Pure{"Name"});
12031 }
12032 elsif($Access1 ne "protected"
12033 and $Access1 ne "private"
12034 and $Access2 eq "protected")
12035 {
12036 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12037 "Target"=>$Member_Name,
12038 "Type_Name"=>$Type1_Pure{"Name"});
12039 }
12040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012041 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12042 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012043 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12045 $SizeV1 = $BSize1;
12046 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012047 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12049 $SizeV2 = $BSize2;
12050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012051 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12052 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012053 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012054 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012055 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012056 {
12057 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12058 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12059 { # field size change (including anon-structures and unions)
12060 # - same types
12061 # - unnamed types
12062 # - bitfields
12063 my $ProblemType = "Field_Size";
12064 if(not isPublic(\%Type1_Pure, $Member_Pos)
12065 or isUnnamed($Member_Name))
12066 { # should not be accessed by applications, goes to "Low Severity"
12067 # example: "abidata" members in GStreamer types
12068 $ProblemType = "Private_".$ProblemType;
12069 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012070 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 +040012071 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012072 if($Type2_Pure{"Type"} ne "Union"
12073 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012075 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 +040012076 { # changed offset
12077 $ProblemType .= "_And_Layout";
12078 }
12079 }
12080 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12081 $ProblemType .= "_And_Type_Size";
12082 }
12083 }
12084 if($ProblemType eq "Private_Field_Size")
12085 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012086 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012087 if($ProblemType eq "Field_Size")
12088 {
12089 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12090 { # Low severity
12091 $ProblemType = "Struct_Field_Size_Increased";
12092 }
12093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 if($ProblemType)
12095 { # register a problem
12096 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12097 "Target"=>$Member_Name,
12098 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012099 "Old_Size"=>$SizeV1,
12100 "New_Size"=>$SizeV2);
12101 }
12102 }
12103 }
12104 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12105 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12106 { # do NOT check bitfield type changes
12107 next;
12108 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012109 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012110 {
12111 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12112 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12113 {
12114 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12115 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012116 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012117 }
12118 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12119 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12120 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012121 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012122 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012123 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012124 }
12125 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012126 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12127 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012129 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12130 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012131
12132 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012133 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012134 or $ProblemType eq "Field_Type_And_Size"
12135 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012137 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012138 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012139 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012140 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012141 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012142 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012143 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012144 }
12145 }
12146 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12147 {
12148 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012149 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012150 }
12151 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012152 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012153 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012154 }
12155 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12156 {
12157 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012158 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012159 }
12160 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012161 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012162 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012163 }
12164 }
12165 }
12166
12167 if($Level eq "Source")
12168 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012169 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012170 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012171 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12172 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012173
12174 if($ProblemType eq "Field_Type")
12175 {
12176 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012177 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012178 }
12179 }
12180 }
12181 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012182
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012183 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 {
12185 my $ProblemType_Init = $ProblemType;
12186 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012187 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012188 if(not isPublic(\%Type1_Pure, $Member_Pos)
12189 or isUnnamed($Member_Name)) {
12190 $ProblemType = "Private_".$ProblemType;
12191 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012192 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 +040012193 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012194 if($Type2_Pure{"Type"} ne "Union"
12195 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012196 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012197 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 +040012198 { # changed offset
12199 $ProblemType .= "_And_Layout";
12200 }
12201 }
12202 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12203 $ProblemType .= "_And_Type_Size";
12204 }
12205 }
12206 }
12207 else
12208 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012209 # TODO: Private_Field_Type rule?
12210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 if(not isPublic(\%Type1_Pure, $Member_Pos)
12212 or isUnnamed($Member_Name)) {
12213 next;
12214 }
12215 }
12216 if($ProblemType eq "Private_Field_Type_And_Size")
12217 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 }
12219 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12220 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012221 "Type_Name"=>$Type1_Pure{"Name"});
12222
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012223 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012224 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012225 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012226 }
12227 }
12228 if(not isPublic(\%Type1_Pure, $Member_Pos))
12229 { # do NOT check internal type changes
12230 next;
12231 }
12232 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012233 { # checking member type changes
12234 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12235
12236 my %DupProblems = ();
12237
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012238 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012239 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012240 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012241 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012242 if(not defined $AllAffected)
12243 {
12244 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12245 next;
12246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012248
12249 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12250 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12251
12252 if(not defined $AllAffected)
12253 {
12254 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012255 }
12256 }
12257 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012258
12259 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260 }
12261 }
12262 }
12263 }
12264 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12265 { # checking added members, public and private
12266 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12267 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012268 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012269 if($AddedField{$Member_Pos})
12270 { # added
12271 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12272 {
12273 my $ProblemType = "Added_Field";
12274 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012275 or isUnnamed($Member_Name))
12276 {
12277 if($Level eq "Source") {
12278 next;
12279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012280 $ProblemType = "Added_Private_Field";
12281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012282 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012283 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012284 {
12285 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12286 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012287 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 +040012288 { # changed offset
12289 $ProblemType .= "_And_Layout";
12290 }
12291 }
12292 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12293 $ProblemType .= "_And_Size";
12294 }
12295 }
12296 if($ProblemType eq "Added_Private_Field")
12297 { # skip added private fields
12298 next;
12299 }
12300 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12301 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012302 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 }
12304 elsif($Type2_Pure{"Type"} eq "Union")
12305 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012306 if($Level eq "Binary"
12307 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012308 {
12309 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12310 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012311 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012312 }
12313 else
12314 {
12315 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12316 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012317 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012318 }
12319 }
12320 elsif($Type2_Pure{"Type"} eq "Enum")
12321 {
12322 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12323 next if($Member_Value eq "");
12324 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12325 "Target"=>$Member_Name,
12326 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012327 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012328 }
12329 }
12330 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012331
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012332 if($Type1_Pure{"Type"} eq "FuncPtr")
12333 {
12334 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12335 {
12336 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12337 next;
12338 }
12339
12340 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12341 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12342
12343 my $PName = "p".$PPos;
12344
12345 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12346 my %DupProblems = ();
12347
12348 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12349 {
12350 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12351 {
12352 if(not defined $AllAffected)
12353 {
12354 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12355 next;
12356 }
12357 }
12358
12359 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12360 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12361
12362 if(not defined $AllAffected)
12363 {
12364 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12365 }
12366 }
12367 }
12368
12369 %DupProblems = ();
12370 }
12371 }
12372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012373 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012374 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375}
12376
12377sub isUnnamed($) {
12378 return $_[0]=~/\Aunnamed\d+\Z/;
12379}
12380
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012381sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012382{
12383 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012384 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12385 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12386 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012388 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012389 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012390 }
12391 return $TypeName;
12392}
12393
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012394sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012395{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012396 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012397 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012398 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12399 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012400 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012401 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12402 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403 return () if(not $Type{"Type"});
12404 if($Type{"Type"} ne $Type_Type)
12405 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012406 return () if(not $Type{"BaseType"});
12407 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012408 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012409 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410 return %Type;
12411}
12412
12413my %TypeSpecAttributes = (
12414 "Const" => 1,
12415 "Volatile" => 1,
12416 "ConstVolatile" => 1,
12417 "Restrict" => 1,
12418 "Typedef" => 1
12419);
12420
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012421sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012422{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012423 my ($TypeId, $Info) = @_;
12424 if(not $TypeId or not $Info
12425 or not $Info->{$TypeId}) {
12426 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012427 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012428 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12429 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12430 }
12431 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012432 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012434 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012436 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012437 return %Type;
12438}
12439
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012440sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012442 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012443 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012444 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12445 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012447 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12448 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012449 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12450 my $PLevel = 0;
12451 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12452 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012454 return $PLevel if(not $Type{"BaseType"});
12455 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12456 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12457 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012458}
12459
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012460sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012462 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012464 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12465 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012467 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12468 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012469 return %Type if(not $Type{"BaseType"});
12470 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012471 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012472 return %Type;
12473}
12474
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012475sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012477 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012478 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12480 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012481 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012482 my $Qual = "";
12483 if($Type{"Type"} eq "Pointer") {
12484 $Qual .= "*";
12485 }
12486 elsif($Type{"Type"} eq "Ref") {
12487 $Qual .= "&";
12488 }
12489 elsif($Type{"Type"} eq "ConstVolatile") {
12490 $Qual .= "const volatile";
12491 }
12492 elsif($Type{"Type"} eq "Const"
12493 or $Type{"Type"} eq "Volatile"
12494 or $Type{"Type"} eq "Restrict") {
12495 $Qual .= lc($Type{"Type"});
12496 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012497 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012498 return $BQual.$Qual;
12499}
12500
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012501sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012502{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012503 my ($TypeId, $Info) = @_;
12504 if(not $TypeId or not $Info
12505 or not $Info->{$TypeId}) {
12506 return ();
12507 }
12508 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012509 return %Type if(not $Type{"BaseType"});
12510 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012511 {
12512 if($Info->{$BTid}) {
12513 return %{$Info->{$BTid}};
12514 }
12515 else { # something is going wrong
12516 return ();
12517 }
12518 }
12519 else {
12520 return %Type;
12521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522}
12523
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012524sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012525{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012526 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012527 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012528 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12529 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012530}
12531
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012532sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012533{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012534 my $Symbol = $_[0];
12535 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12536}
12537
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012538sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012539 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12540}
12541
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012542sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012544 my ($SInfo, $LibVersion) = @_;
12545
12546 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012547 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012548 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012549 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012550 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012551 return 1;
12552 }
12553 }
12554 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012555 if(my $ShortName = $SInfo->{"ShortName"})
12556 {
12557 if(index($ShortName,"<")!=-1
12558 and index($ShortName,">")!=-1) {
12559 return 1;
12560 }
12561 }
12562
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012563 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012564}
12565
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012566sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012568 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012569 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012571 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572 { # class specialization
12573 return 1;
12574 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012575 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012576 { # method specialization
12577 return 1;
12578 }
12579 }
12580 return 0;
12581}
12582
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012583sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012584{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012585 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012586
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012587 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 { # non-public global data
12589 return 0;
12590 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012591
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012592 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012593 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012594 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012595 }
12596
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012597 if($Symbol=~/\A_Z/)
12598 {
12599 if($Symbol=~/[CD][3-4]E/) {
12600 return 0;
12601 }
12602 }
12603
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 { # support for old ABI dumps in --headers-only mode
12606 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12607 {
12608 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12609 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012610 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012611 if(not $PType or $PType eq "Unknown") {
12612 return 0;
12613 }
12614 }
12615 }
12616 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012617 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012619 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12620
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621 if($SkipSymbols{$LibVersion}{$Symbol})
12622 { # user defined symbols to ignore
12623 return 0;
12624 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012625
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012626 if($SymbolsListPath and not $SymbolsList{$Symbol})
12627 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012628 if(not $TargetHeadersPath or not $Header
12629 or not is_target_header($Header, 1))
12630 { # -symbols-list | -headers-list
12631 return 0;
12632 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012633 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012634
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012635 if($AppPath and not $SymbolsList_App{$Symbol})
12636 { # user defined symbols (in application)
12637 return 0;
12638 }
12639
12640 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12641
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012642 if($ClassId)
12643 {
12644 if(not isTargetType($ClassId, $LibVersion)) {
12645 return 0;
12646 }
12647 }
12648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012649 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12650 if(not $NameSpace and $ClassId)
12651 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012652 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012653 }
12654 if($NameSpace)
12655 { # user defined namespaces to ignore
12656 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12657 return 0;
12658 }
12659 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12660 { # nested namespaces
12661 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12662 return 0;
12663 }
12664 }
12665 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012666 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012667 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012668 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012669 { # --skip-headers or <skip_headers> (not <skip_including>)
12670 if($Skip==1) {
12671 return 0;
12672 }
12673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012674 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012675 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012676 { # user defined types
12677 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12678
12679 if(not $TypesList{$CName})
12680 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012681 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12682 {
12683 $CName=~s/\A\Q$NS\E\:\://g;
12684 }
12685
12686 if(not $TypesList{$CName})
12687 {
12688 my $Found = 0;
12689
12690 while($CName=~s/\:\:.+?\Z//)
12691 {
12692 if($TypesList{$CName})
12693 {
12694 $Found = 1;
12695 last;
12696 }
12697 }
12698
12699 if(not $Found) {
12700 return 0;
12701 }
12702 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012703 }
12704 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012705
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012706 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12707 { # non-target symbols
12708 return 0;
12709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012710 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012711 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012712 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12713 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012714 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012715 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12716 { # inline virtual methods
12717 if($Type=~/InlineVirt/) {
12718 return 1;
12719 }
12720 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12721 if(not $Allocable)
12722 { # check bases
12723 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12724 {
12725 if(not isCopyingClass($DCId, $LibVersion))
12726 { # exists a derived class without default c-tor
12727 $Allocable=1;
12728 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012730 }
12731 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012732 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012733 return 0;
12734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012736 else
12737 { # inline non-virtual methods
12738 return 0;
12739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012741 }
12742 }
12743 return 1;
12744}
12745
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012746sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012747{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012748 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012749 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12750 {
12751 if(link_symbol($Symbol, 1, "+Deps"))
12752 { # linker can find a new symbol
12753 # in the old-version library
12754 # So, it's not a new symbol
12755 next;
12756 }
12757 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012758 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759 next;
12760 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012761 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012762 }
12763}
12764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012765sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012766{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012768 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12769 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012770 if(link_symbol($Symbol, 2, "+Deps"))
12771 { # linker can find an old symbol
12772 # in the new-version library
12773 next;
12774 }
12775 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012776 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012777 next;
12778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012779 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 }
12781}
12782
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012783sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012784{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012785 my $Level = $_[0];
12786 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012787 { # checking added symbols
12788 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012789 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012790 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012791 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012793 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012794 { # checking removed symbols
12795 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012796 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012797 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 { # skip v-tables for templates, that should not be imported by applications
12799 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012800 if(my $CName = $VTableClass{$Symbol})
12801 {
12802 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12803 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012804 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012805 next;
12806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012807 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012808
12809 if($SkipSymbols{1}{$Symbol})
12810 { # user defined symbols to ignore
12811 next;
12812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 }
12814 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012815 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012816 }
12817 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12818 { # symbols for pure virtual methods cannot be called by clients
12819 next;
12820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012821 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012822 }
12823}
12824
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012825sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012826{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012827 my ($LibVersion, $V) = @_;
12828 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12829 return $Cache{"checkDump"}{$LibVersion}{$V};
12830 }
12831 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012832}
12833
12834sub detectAdded_H($)
12835{
12836 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12838 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012839 if($Level eq "Source")
12840 { # remove symbol version
12841 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12842 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012843
12844 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12845 { # skip artificial constructors
12846 next;
12847 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012849 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12850 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012851 next;
12852 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012853 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012854 next;
12855 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012856 if(not defined $CompleteSignature{1}{$Symbol}
12857 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12858 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012859 if($UsedDump{2}{"SrcBin"})
12860 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012861 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012862 { # support for old and different (!) ABI dumps
12863 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12864 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012865 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012866 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012867 {
12868 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12869 {
12870 if($Lang eq "C")
12871 { # support for old ABI dumps: missed extern "C" functions
12872 next;
12873 }
12874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012875 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012876 else
12877 {
12878 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012879 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012880 next;
12881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012882 }
12883 }
12884 }
12885 }
12886 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012887 }
12888 }
12889}
12890
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012891sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012892{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012893 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12895 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012896 if($Level eq "Source")
12897 { # remove symbol version
12898 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12899 $Symbol=$SN;
12900 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012901 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12902 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 next;
12904 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012905 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012906 next;
12907 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012908 if(not defined $CompleteSignature{2}{$Symbol}
12909 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012910 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012911 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012913 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012914 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012915 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12916 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012918 if($CheckHeadersOnly)
12919 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012920 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12921 {
12922 if($Lang eq "C")
12923 { # support for old ABI dumps: missed extern "C" functions
12924 next;
12925 }
12926 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012927 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012928 else
12929 {
12930 if(not link_symbol($Symbol, 1, "-Deps"))
12931 { # skip removed inline symbols
12932 next;
12933 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012934 }
12935 }
12936 }
12937 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012938 if(not checkDump(1, "2.15"))
12939 {
12940 if($Symbol=~/_IT_E\Z/)
12941 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12942 next;
12943 }
12944 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012945 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12946 {
12947 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12948 {
12949 if(defined $Constants{2}{$Short})
12950 {
12951 my $Val = $Constants{2}{$Short}{"Value"};
12952 if(defined $Func_ShortName{2}{$Val})
12953 { # old name defined to new
12954 next;
12955 }
12956 }
12957 }
12958
12959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012960 $RemovedInt{$Level}{$Symbol} = 1;
12961 if($Level eq "Source")
12962 { # search for a source-compatible equivalent
12963 setAlternative($Symbol, $Level);
12964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012965 }
12966 }
12967}
12968
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012971 my $Level = $_[0];
12972 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012973 { # checking added symbols
12974 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012975 next if($CompleteSignature{2}{$Symbol}{"Private"});
12976 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012977 if($Level eq "Binary")
12978 {
12979 if($CompleteSignature{2}{$Symbol}{"InLine"})
12980 {
12981 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12982 { # skip inline non-virtual functions
12983 next;
12984 }
12985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012986 }
12987 else
12988 { # Source
12989 if($SourceAlternative_B{$Symbol}) {
12990 next;
12991 }
12992 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012993 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012995 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012996 { # checking removed symbols
12997 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012998 next if($CompleteSignature{1}{$Symbol}{"Private"});
12999 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013000 if($Level eq "Binary")
13001 {
13002 if($CompleteSignature{1}{$Symbol}{"InLine"})
13003 {
13004 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13005 { # skip inline non-virtual functions
13006 next;
13007 }
13008 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013009 }
13010 else
13011 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013012 if(my $Alt = $SourceAlternative{$Symbol})
13013 {
13014 if(defined $CompleteSignature{1}{$Alt}
13015 and $CompleteSignature{1}{$Symbol}{"Const"})
13016 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013017 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013018 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013019 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013020 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013021 }
13022 else
13023 { # do NOT show removed symbol
13024 next;
13025 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013026 }
13027 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013028 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013029 }
13030}
13031
13032sub addParamNames($)
13033{
13034 my $LibraryVersion = $_[0];
13035 return if(not keys(%AddIntParams));
13036 my $SecondVersion = $LibraryVersion==1?2:1;
13037 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13038 {
13039 next if(not keys(%{$AddIntParams{$Interface}}));
13040 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013041 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013042 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13043 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013044 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13046 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13047 {
13048 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13049 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13050 }
13051 }
13052 else {
13053 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13054 }
13055 }
13056 }
13057 }
13058}
13059
13060sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013061{ # detect changed typedefs to show
13062 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013063 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13064 {
13065 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013066 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13067 if(not $BName1 or isAnon($BName1)) {
13068 next;
13069 }
13070 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13071 if(not $BName2 or isAnon($BName2)) {
13072 next;
13073 }
13074 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013075 $ChangedTypedef{$Typedef} = 1;
13076 }
13077 }
13078}
13079
13080sub get_symbol_suffix($$)
13081{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013082 my ($Symbol, $Full) = @_;
13083 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013084 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013086 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013087 if(not $Full) {
13088 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13089 }
13090 return $Suffix;
13091}
13092
13093sub get_symbol_prefix($$)
13094{
13095 my ($Symbol, $LibVersion) = @_;
13096 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13097 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13098 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013099 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013100 }
13101 return $ShortName;
13102}
13103
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013104sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013105{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013106 my $Symbol = $_[0];
13107 my $PSymbol = $Symbol;
13108 if(not defined $CompleteSignature{2}{$PSymbol}
13109 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13110 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13111 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013112 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013114 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013115 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013116 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13117 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013118 {
13119 if(defined $CompleteSignature{2}{$PSymbol}
13120 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13121 {
13122 $SourceAlternative{$Symbol} = $PSymbol;
13123 $SourceAlternative_B{$PSymbol} = $Symbol;
13124 if(not defined $CompleteSignature{1}{$PSymbol}
13125 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13126 $SourceReplacement{$Symbol} = $PSymbol;
13127 }
13128 }
13129 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013130 }
13131 else
13132 {
13133 foreach my $Sp ("KV", "VK", "K", "V")
13134 {
13135 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13136 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13137 {
13138 if(defined $CompleteSignature{2}{$PSymbol}
13139 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13140 {
13141 $SourceAlternative{$Symbol} = $PSymbol;
13142 $SourceAlternative_B{$PSymbol} = $Symbol;
13143 if(not defined $CompleteSignature{1}{$PSymbol}
13144 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13145 $SourceReplacement{$Symbol} = $PSymbol;
13146 }
13147 }
13148 }
13149 $PSymbol = $Symbol;
13150 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 }
13152 }
13153 }
13154 return "";
13155}
13156
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013157sub getSymKind($$)
13158{
13159 my ($Symbol, $LibVersion) = @_;
13160 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13161 {
13162 return "Global_Data";
13163 }
13164 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13165 {
13166 return "Method";
13167 }
13168 return "Function";
13169}
13170
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013171sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013172{
13173 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013174 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013175
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013176 mergeBases($Level);
13177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013179 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013180 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013182 next;
13183 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013184 if(defined $CompleteSignature{1}{$Symbol}
13185 and $CompleteSignature{1}{$Symbol}{"Header"})
13186 { # double-check added symbol
13187 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013189 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013190 next;
13191 }
13192 if($Symbol=~/\A(_Z|\?)/)
13193 { # C++
13194 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13195 }
13196 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13197 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013198 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13199 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013200 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013202 {
13203 if($TName_Tid{1}{$AffectedClass_Name})
13204 { # class should exist in previous version
13205 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13206 { # old v-table is NOT copied by old applications
13207 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13208 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013209 "Target"=>get_Signature($Symbol, 2),
13210 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013211 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013214 }
13215 }
13216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013217 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13218 { # check all removed exported symbols
13219 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013220 next;
13221 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013222 if(defined $CompleteSignature{2}{$Symbol}
13223 and $CompleteSignature{2}{$Symbol}{"Header"})
13224 { # double-check removed symbol
13225 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 }
13227 if($CompleteSignature{1}{$Symbol}{"Private"})
13228 { # skip private methods
13229 next;
13230 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013231 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013232 next;
13233 }
13234 $CheckedSymbols{$Level}{$Symbol} = 1;
13235 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13236 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013237 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13238 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013239 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013240 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13241 {
13242 if($TName_Tid{2}{$AffectedClass_Name})
13243 { # class should exist in newer version
13244 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13245 { # old v-table is NOT copied by old applications
13246 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13247 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013248 "Target"=>get_Signature($OverriddenMethod, 1),
13249 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013250 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013253 }
13254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013255 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013256 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013257 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013258 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013259 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013260 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013261 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013262 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013264 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013265 {
13266 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13267 "Target"=>$tr_name{$Symbol},
13268 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013271 else
13272 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013273 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013274 "Target"=>$tr_name{$Symbol},
13275 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013276 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 }
13278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013279 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013281 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013282 {
13283 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13284 "Target"=>$tr_name{$Symbol},
13285 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013286 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013288 else
13289 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013290 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013291 "Target"=>$tr_name{$Symbol},
13292 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013293 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013294 }
13295 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013296 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13297 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13298 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13299 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13300 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013301 {
13302 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013303 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013304 $ProblemType = "Global_Data_Symbol_Changed_Type";
13305 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013306 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13307 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013308 "Old_Type"=>$RTName1,
13309 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013310 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013311 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013312 }
13313 }
13314 }
13315 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013316 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013317 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013318 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013319 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013320 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013322 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013323 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13324 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013325 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013326 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013328 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013329 }
13330 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013331 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13332 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013333 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013334 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013335 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013336 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 }
13338 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013339 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013340 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013341 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013343 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013344 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013345 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013346 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013347 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013348 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013350 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013351 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013356 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013357 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013358 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 { # "volatile" to non-"volatile"
13365
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013366 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013367 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013368 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013370 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013371 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013375 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013377 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013379 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013380 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013381 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013382 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13384 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013385 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013387 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013388 }
13389 }
13390 }
13391 }
13392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013393 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13394 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013395 $CurrentSymbol = $Symbol;
13396
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13398 if($Level eq "Source")
13399 { # remove symbol version
13400 $Symbol=$SN;
13401 }
13402 else
13403 { # Binary
13404 if(not $SV)
13405 { # symbol without version
13406 if(my $VSym = $SymVer{1}{$Symbol})
13407 { # the symbol is linked with versioned symbol
13408 if($CompleteSignature{2}{$VSym}{"MnglName"})
13409 { # show report for symbol@ver only
13410 next;
13411 }
13412 elsif(not link_symbol($VSym, 2, "-Deps"))
13413 { # changed version: sym@v1 to sym@v2
13414 # do NOT show report for symbol
13415 next;
13416 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013417 }
13418 }
13419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013420 my $PSymbol = $Symbol;
13421 if($Level eq "Source"
13422 and my $S = $SourceReplacement{$Symbol})
13423 { # take a source-compatible replacement function
13424 $PSymbol = $S;
13425 }
13426 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013427 { # private symbols
13428 next;
13429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013430 if(not defined $CompleteSignature{1}{$Symbol}
13431 or not defined $CompleteSignature{2}{$PSymbol})
13432 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 next;
13434 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013435 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13436 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13437 { # no mangled name
13438 next;
13439 }
13440 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13441 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013442 { # without a header
13443 next;
13444 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013445
13446 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13447 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13448 { # became pure
13449 next;
13450 }
13451 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13452 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13453 { # became non-pure
13454 next;
13455 }
13456
13457 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13458 { # exported, target, inline virtual and pure virtual
13459 next;
13460 }
13461 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13462 { # exported, target, inline virtual and pure virtual
13463 next;
13464 }
13465
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013466 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013467 {
13468 if($CompleteSignature{1}{$Symbol}{"Data"}
13469 and $CompleteSignature{2}{$PSymbol}{"Data"})
13470 {
13471 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13472 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13473 if(defined $Value1)
13474 {
13475 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13476 if(defined $Value2)
13477 {
13478 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13479 if($Value1 ne $Value2)
13480 {
13481 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13482 "Old_Value"=>$Value1,
13483 "New_Value"=>$Value2,
13484 "Target"=>get_Signature($Symbol, 1) );
13485 }
13486 }
13487 }
13488 }
13489 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013490
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013491 if($CompleteSignature{2}{$PSymbol}{"Private"})
13492 {
13493 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13494 "Target"=>get_Signature_M($PSymbol, 2) );
13495 }
13496 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13497 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13498 {
13499 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13500 "Target"=>get_Signature_M($PSymbol, 2) );
13501 }
13502 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13503 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13504 {
13505 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13506 "Target"=>get_Signature_M($PSymbol, 2) );
13507 }
13508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013509 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013510 mergeVirtualTables($Symbol, $Level);
13511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013512 if($COMPILE_ERRORS)
13513 { # if some errors occurred at the compiling stage
13514 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013515 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013516 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013517 { # missed information about parameters in newer version
13518 next;
13519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013520 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013521 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013522 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 next;
13524 }
13525 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013526 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013527 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013528 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013529 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13530 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013531 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13532 "Target"=>get_Signature($Symbol, 1)
13533 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013534 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013535 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013536 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13537 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013538 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013539 "Target"=>get_Signature($Symbol, 1)
13540 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013541 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13543 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013544 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013546 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013547 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13548 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13549 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013550 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013551 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013552 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13553 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013554 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013555 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013556 my $ProblemType = "Virtual_Method_Position";
13557 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13558 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013560 if(isUsedClass($Class_Id, 1, $Level))
13561 {
13562 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013563 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013564 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013565 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13566 next;
13567 }
13568 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013569 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013570 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13571 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013572 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013574 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 }
13577 }
13578 }
13579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013580 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13581 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013582 { # do NOT check type changes in pure virtuals
13583 next;
13584 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013585 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013586 if($Symbol=~/\A(_Z|\?)/
13587 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013588 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013589 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013590 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013591 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013592 }
13593 }
13594 else
13595 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013596 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013598 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013599 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13600 last if($PType2_Name eq "...");
13601 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13602 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013603 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013604 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013606 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13607 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13609 $ParamPos_Prev = "lost";
13610 }
13611 }
13612 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013613 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013614 }
13615 if($ParamPos_Prev eq "lost")
13616 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013617 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013618 {
13619 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013620 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 $ProblemType = "Added_Unnamed_Parameter";
13622 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013623 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013624 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013625 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013626 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013627 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 }
13629 else
13630 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013631 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013632 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013633 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013634 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13635 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013636 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013637 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013638 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013639 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013640 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013641 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013642 "Param_Type"=>$PType2_Name,
13643 "Old_Value"=>$PName_Old,
13644 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013645 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013646 }
13647 }
13648 else
13649 {
13650 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013651 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013652 $ProblemType = "Added_Middle_Unnamed_Parameter";
13653 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013654 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013655 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013656 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013657 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013658 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013659 }
13660 }
13661 }
13662 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013663 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013664 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013665 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013666 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013668 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013669 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013670 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013671 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013672 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13673 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013674 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013675 }
13676 }
13677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013678 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013679 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013680 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013681 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13682 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013683 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13684 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013685 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013686 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013687 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013688 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13689 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013690 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13691 $ParamPos_New = "lost";
13692 }
13693 }
13694 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013695 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013696 }
13697 if($ParamPos_New eq "lost")
13698 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013699 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 {
13701 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013702 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 $ProblemType = "Removed_Unnamed_Parameter";
13704 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013705 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013706 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013707 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013708 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013709 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013710 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013711 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013712 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013713 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013714 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013715 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013716 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013717 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013718 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013719 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013720 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013721 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013722 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013723 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013724 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013725 "Old_Value"=>$PName,
13726 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013727 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013728 }
13729 }
13730 else
13731 {
13732 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013733 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13735 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013736 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013737 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013738 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013739 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013740 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 }
13742 }
13743 }
13744 }
13745 }
13746 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013747 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13748 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013749 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013750
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013751 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013752 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013753 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13754 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013755 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013756
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013757 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013758 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013759 if($SubProblemType eq "Return_Type_And_Size") {
13760 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13761 }
13762 elsif($SubProblemType eq "Return_Type_Format") {
13763 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13764 }
13765 else {
13766 $ProblemTypes{"Global_Data_Type"} = 1;
13767 }
13768
13769 # quals
13770 if($SubProblemType eq "Return_Type"
13771 or $SubProblemType eq "Return_Type_And_Size"
13772 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013773 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013774 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13775 { # const to non-const
13776 if($RR==2) {
13777 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13778 }
13779 else {
13780 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13781 }
13782 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013783 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013784 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13785 { # non-const to const
13786 if($RA==2) {
13787 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13788 }
13789 else {
13790 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13791 }
13792 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 }
13794 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013795 }
13796 else
13797 {
13798 # quals
13799 if($SubProblemType eq "Return_Type"
13800 or $SubProblemType eq "Return_Type_And_Size"
13801 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013803 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013804 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013805 if(addedQual($Old_Value, $New_Value, "volatile"))
13806 {
13807 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13808 if($Level ne "Source"
13809 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13810 $ProblemTypes{"Return_Type"} = 1;
13811 }
13812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013813 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013814 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13815 {
13816 if($RA==2) {
13817 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13818 }
13819 else {
13820 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13821 }
13822 if($Level ne "Source"
13823 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13824 $ProblemTypes{"Return_Type"} = 1;
13825 }
13826 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013827 }
13828 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013829 if($Level eq "Binary"
13830 and not $CompleteSignature{1}{$Symbol}{"Data"})
13831 {
13832 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13833 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13834 { # if one of the architectures is unknown
13835 # then set other arhitecture to unknown too
13836 ($Arch1, $Arch2) = ("unknown", "unknown");
13837 }
13838 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013839 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013840 {
13841 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13842 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13843 }
13844 else
13845 {
13846 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13847 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13848 }
13849
13850 if($SubProblemType eq "Return_Type_Became_Void")
13851 {
13852 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13853 { # parameters stack has been affected
13854 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013856 }
13857 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 }
13860 }
13861 }
13862 elsif($SubProblemType eq "Return_Type_From_Void")
13863 {
13864 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13865 { # parameters stack has been affected
13866 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013867 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013868 }
13869 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013870 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013871 }
13872 }
13873 }
13874 elsif($SubProblemType eq "Return_Type"
13875 or $SubProblemType eq "Return_Type_And_Size"
13876 or $SubProblemType eq "Return_Type_Format")
13877 {
13878 if($Conv1{"Method"} ne $Conv2{"Method"})
13879 {
13880 if($Conv1{"Method"} eq "stack")
13881 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013882 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013883 }
13884 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013885 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013886 }
13887 }
13888 else
13889 {
13890 if($Conv1{"Method"} eq "reg")
13891 {
13892 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13893 {
13894 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013895 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013896 }
13897 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013899 }
13900 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013901 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013902 }
13903 }
13904 }
13905 }
13906 }
13907 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013908
13909 if(not keys(%ProblemTypes))
13910 { # default
13911 $ProblemTypes{$SubProblemType} = 1;
13912 }
13913
13914 foreach my $ProblemType (keys(%ProblemTypes))
13915 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013916 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013918 }
13919 if($ReturnType1_Id and $ReturnType2_Id)
13920 {
13921 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013922 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13923
13924 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013925
13926 if($CompleteSignature{1}{$Symbol}{"Data"})
13927 {
13928 if($Level eq "Binary")
13929 {
13930 if(get_PLevel($ReturnType1_Id, 1)==0)
13931 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013932 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013933 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013934
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013935 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13936 {
13937 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013938 {
13939 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13940 {
13941 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13942 last;
13943 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013944 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013945 }
13946 }
13947 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013948 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013949 {
13950 if(defined $GlobalDataObject{1}{$Symbol}
13951 and defined $GlobalDataObject{2}{$Symbol})
13952 {
13953 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13954 my $New_Size = $GlobalDataObject{2}{$Symbol};
13955 if($Old_Size!=$New_Size)
13956 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013957 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013958 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013959 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013960 }
13961 }
13962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013963 }
13964 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013965
13966 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013967 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013968 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013969 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013970 my $NewLocation = "retval";
13971 if($SubLocation and $SubLocation ne "retval") {
13972 $NewLocation = "retval->".$SubLocation;
13973 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013974 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13975 }
13976 }
13977
13978 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13979 {
13980 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13981 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013982 my $NewLocation = "retval";
13983 if($SubLocation and $SubLocation ne "retval") {
13984 $NewLocation = "retval->".$SubLocation;
13985 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013986 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013987 }
13988 }
13989 }
13990
13991 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013992 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13993 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13994 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013995 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013996 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013997 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13998 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013999 if($ThisPtr1_Id and $ThisPtr2_Id)
14000 {
14001 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014002 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14003 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014004 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014005 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014006 {
14007 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014008 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014009 }
14010 }
14011 }
14012 }
14013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014014 if($Level eq "Binary") {
14015 mergeVTables($Level);
14016 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014017 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14018 $CheckedSymbols{$Level}{$Symbol} = 1;
14019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014020}
14021
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014022sub rmQuals($$)
14023{
14024 my ($Value, $Qual) = @_;
14025 if(not $Qual) {
14026 return $Value;
14027 }
14028 if($Qual eq "all")
14029 { # all quals
14030 $Qual = "const|volatile|restrict";
14031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014032 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014033 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014034 }
14035 return $Value;
14036}
14037
14038sub cmpBTypes($$$$)
14039{
14040 my ($T1, $T2, $V1, $V2) = @_;
14041 $T1 = uncover_typedefs($T1, $V1);
14042 $T2 = uncover_typedefs($T2, $V2);
14043 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14044}
14045
14046sub addedQual($$$)
14047{
14048 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014049 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014050}
14051
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014052sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014053{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014054 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014055 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014056}
14057
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014058sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014059{
14060 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14061 $Old_Value = uncover_typedefs($Old_Value, $V1);
14062 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014063
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014064 if($Old_Value eq $New_Value)
14065 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014066 return 0;
14067 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014068 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014069 { # without a qual
14070 return 0;
14071 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014072 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014073 { # became non-qual
14074 return 1;
14075 }
14076 else
14077 {
14078 my @BQ1 = getQualModel($Old_Value, $Qual);
14079 my @BQ2 = getQualModel($New_Value, $Qual);
14080 foreach (0 .. $#BQ1)
14081 { # removed qual
14082 if($BQ1[$_]==1
14083 and $BQ2[$_]!=1)
14084 {
14085 return 2;
14086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014087 }
14088 }
14089 return 0;
14090}
14091
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014092sub getQualModel($$)
14093{
14094 my ($Value, $Qual) = @_;
14095 if(not $Qual) {
14096 return $Value;
14097 }
14098
14099 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014100 while($Value=~/(\w+)/)
14101 {
14102 my $W = $1;
14103
14104 if($W eq $Qual) {
14105 $Value=~s/\b$W\b/\@/g;
14106 }
14107 else {
14108 $Value=~s/\b$W\b//g;
14109 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014110 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014111
14112 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014113 $Value=~s/[^\*\&\w]+//g;
14114
14115 # modeling
14116 # int*const*const == 011
14117 # int**const == 001
14118 my @Model = ();
14119 my @Elems = split(/[\*\&]/, $Value);
14120 if(not @Elems) {
14121 return (0);
14122 }
14123 foreach (@Elems)
14124 {
14125 if($_ eq $Qual) {
14126 push(@Model, 1);
14127 }
14128 else {
14129 push(@Model, 0);
14130 }
14131 }
14132
14133 return @Model;
14134}
14135
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014136my %StringTypes = map {$_=>1} (
14137 "char*",
14138 "char const*"
14139);
14140
14141my %CharTypes = map {$_=>1} (
14142 "char",
14143 "char const"
14144);
14145
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014146sub showVal($$$)
14147{
14148 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014149 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014150 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014151 if(substr($Value, 0, 2) eq "_Z")
14152 {
14153 if(my $Unmangled = $tr_name{$Value}) {
14154 return $Unmangled;
14155 }
14156 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014157 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014158 { # strings
14159 return "\"$Value\"";
14160 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014161 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014162 { # characters
14163 return "\'$Value\'";
14164 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014165 if($Value eq "")
14166 { # other
14167 return "\'\'";
14168 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014169 return $Value;
14170}
14171
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014172sub getRegs($$$)
14173{
14174 my ($LibVersion, $Symbol, $Pos) = @_;
14175
14176 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14177 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014178 my %Regs = ();
14179 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14180 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014181 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014182 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14183 }
14184 }
14185
14186 return join(", ", sort keys(%Regs));
14187 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014188 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14189 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14190 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14191 {
14192 return "unknown";
14193 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014194
14195 return undef;
14196}
14197
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014198sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014199{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014200 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014201 if(not $Symbol) {
14202 return;
14203 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014204 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14205 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14206 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14207 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014208 if(not $PType1_Id
14209 or not $PType2_Id) {
14210 return;
14211 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014212
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014213 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014214 { # do not merge "this"
14215 if($PName1 eq "this" or $PName2 eq "this") {
14216 return;
14217 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014218 }
14219
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014220 my %Type1 = get_Type($PType1_Id, 1);
14221 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014222
14223 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14224
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014225 my %BaseType1 = get_BaseType($PType1_Id, 1);
14226 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014227
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014228 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014229
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014230 if($Level eq "Binary")
14231 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014232 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014233 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14234 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14235 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14236 {
14237 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014238 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014239 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014240 }
14241 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14242 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14243 {
14244 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014245 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014246 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014248 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014249
14250 if(defined $UsedDump{1}{"DWARF"}
14251 and defined $UsedDump{2}{"DWARF"})
14252 {
14253 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14254 {
14255 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14256 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014257
14258 if($Old_Regs ne "unknown"
14259 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014260 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014261 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014262 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014263 if($Old_Regs ne $New_Regs)
14264 {
14265 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14266 "Target"=>$PName1,
14267 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14268 "Old_Value"=>$Old_Regs,
14269 "New_Value"=>$New_Regs );
14270 }
14271 }
14272 elsif($Old_Regs and not $New_Regs)
14273 {
14274 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014275 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014276 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014277 "Old_Value"=>$Old_Regs );
14278 }
14279 elsif(not $Old_Regs and $New_Regs)
14280 {
14281 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14282 "Target"=>$PName1,
14283 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014284 "New_Value"=>$New_Regs );
14285 }
14286 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014287
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014288 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14289 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14290 {
14291 if($Old_Offset ne $New_Offset)
14292 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014293 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14294 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14295
14296 $Old_Offset = $Old_Offset - $Start1;
14297 $New_Offset = $New_Offset - $Start2;
14298
14299 if($Old_Offset ne $New_Offset)
14300 {
14301 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14302 "Target"=>$PName1,
14303 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14304 "Old_Value"=>$Old_Offset,
14305 "New_Value"=>$New_Offset );
14306 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014307 }
14308 }
14309 }
14310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014311 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014312 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14313 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014315 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014316 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14317 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014318 if(not checkDump(1, "2.13")
14319 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014320 { # support for old ABI dumps
14321 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014322 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014323 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014324 and $Value_Old eq "false" and $Value_New eq "0")
14325 { # int class::method ( bool p = 0 );
14326 # old ABI dumps: "false"
14327 # new ABI dumps: "0"
14328 $Value_Old = "0";
14329 }
14330 }
14331 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014332 if(not checkDump(1, "2.18")
14333 and checkDump(2, "2.18"))
14334 { # support for old ABI dumps
14335 if(not defined $Value_Old
14336 and substr($Value_New, 0, 2) eq "_Z") {
14337 $Value_Old = $Value_New;
14338 }
14339 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014340 if(defined $Value_Old)
14341 {
14342 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14343 if(defined $Value_New)
14344 {
14345 $Value_New = showVal($Value_New, $PType2_Id, 2);
14346 if($Value_Old ne $Value_New)
14347 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014348 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014349 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014350 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014351 "Old_Value"=>$Value_Old,
14352 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014353 }
14354 }
14355 else
14356 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014357 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014358 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014359 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014360 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014361 }
14362 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014363 elsif(defined $Value_New)
14364 {
14365 $Value_New = showVal($Value_New, $PType2_Id, 2);
14366 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14367 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014368 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014369 "New_Value"=>$Value_New );
14370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014371 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014372
14373 if($ChkRnmd)
14374 {
14375 if($PName1 and $PName2 and $PName1 ne $PName2
14376 and $PType1_Id!=-1 and $PType2_Id!=-1
14377 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14378 { # except unnamed "..." value list (Id=-1)
14379 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14380 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014381 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014382 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14383 "Old_Value"=>$PName1,
14384 "New_Value"=>$PName2,
14385 "New_Signature"=>get_Signature($Symbol, 2) );
14386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014387 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014389 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014390 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 foreach my $SubProblemType (keys(%SubProblems))
14393 { # add new problems, remove false alarms
14394 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14395 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014396
14397 # quals
14398 if($SubProblemType eq "Parameter_Type"
14399 or $SubProblemType eq "Parameter_Type_And_Size"
14400 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014402 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014403 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014404 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014405 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014406 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014407 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14408 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14409 }
14410 }
14411 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14412 {
14413 if(removedQual($Old_Value, $New_Value, "volatile")) {
14414 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014415 }
14416 }
14417 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14418 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14419 { # int to "int const"
14420 delete($SubProblems{$SubProblemType});
14421 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014422 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014423 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14424 { # "int const" to int
14425 delete($SubProblems{$SubProblemType});
14426 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014427 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14428 { # "const" to non-"const"
14429 if($RR==2) {
14430 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14431 }
14432 else {
14433 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14434 }
14435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014436 }
14437 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014438
14439 if($Level eq "Source")
14440 {
14441 foreach my $SubProblemType (keys(%SubProblems))
14442 {
14443 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14444 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14445
14446 if($SubProblemType eq "Parameter_Type")
14447 {
14448 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14449 delete($SubProblems{$SubProblemType});
14450 }
14451 }
14452 }
14453 }
14454
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014455 foreach my $SubProblemType (keys(%SubProblems))
14456 { # modify/register problems
14457 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14458 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014459 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14460 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014461
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014462 my $NewProblemType = $SubProblemType;
14463 if($Old_Value eq "..." and $New_Value ne "...")
14464 { # change from "..." to "int"
14465 if($ParamPos1==0)
14466 { # ISO C requires a named argument before "..."
14467 next;
14468 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014469 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014470 }
14471 elsif($New_Value eq "..." and $Old_Value ne "...")
14472 { # change from "int" to "..."
14473 if($ParamPos2==0)
14474 { # ISO C requires a named argument before "..."
14475 next;
14476 }
14477 $NewProblemType = "Parameter_Became_VaList";
14478 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014479 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014480 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014481 {
14482 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014483 if($Arch1 eq "unknown"
14484 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014485 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014486 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014487 ($Arch1, $Arch2) = ("unknown", "unknown");
14488 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014489 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014490 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014491 { # real
14492 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14493 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14494 }
14495 else
14496 { # model
14497 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14498 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14499 }
14500 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014501 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014502 if($Conv1{"Method"} eq "stack")
14503 {
14504 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14505 $NewProblemType = "Parameter_Type_And_Stack";
14506 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014507 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014508 elsif($Conv1{"Method"} eq "reg")
14509 {
14510 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14511 $NewProblemType = "Parameter_Type_And_Register";
14512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014513 }
14514 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014515 elsif($Conv1{"Method"} ne "unknown"
14516 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014517 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014518 if($Conv1{"Method"} eq "stack") {
14519 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014521 elsif($Conv1{"Method"} eq "register") {
14522 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014523 }
14524 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014525 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14526 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014527 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014528 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014529 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014530 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014531 "New_Signature"=>get_Signature($Symbol, 2) );
14532 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014533 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014535 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014536
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014537 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014538 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14539 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014541 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014542 {
14543 my $NewProblemType = $SubProblemType;
14544 if($SubProblemType eq "DataType_Size")
14545 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014546 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014547 { # stack has been affected
14548 $NewProblemType = "DataType_Size_And_Stack";
14549 }
14550 }
14551 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014552 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014553 }
14554 }
14555}
14556
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014557sub find_ParamPair_Pos_byName($$$)
14558{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014559 my ($Name, $Symbol, $LibVersion) = @_;
14560 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014561 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014562 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14563 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014564 {
14565 return $ParamPos;
14566 }
14567 }
14568 return "lost";
14569}
14570
14571sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14572{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014573 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014575 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576 {
14577 next if($Order eq "backward" and $ParamPos>$MediumPos);
14578 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014579 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14580 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014581 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014582 push(@Positions, $ParamPos);
14583 }
14584 }
14585 return @Positions;
14586}
14587
14588sub getTypeIdByName($$)
14589{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014590 my ($TypeName, $LibVersion) = @_;
14591 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014592}
14593
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014594sub diffTypes($$$)
14595{
14596 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14597 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14598 }
14599 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14600 { # skip recursive declarations
14601 return 0;
14602 }
14603
14604 pushType($_[0], $_[1], \@RecurTypes_Diff);
14605 my $Diff = diffTypes_I(@_);
14606 pop(@RecurTypes_Diff);
14607
14608 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14609}
14610
14611sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014612{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014613 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014614
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014615 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14616 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014617
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014618 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14619 { # equal types
14620 return 0;
14621 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014622 if($Type1_Pure{"Name"} eq "void")
14623 { # from void* to something
14624 return 0;
14625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014626 if($Type1_Pure{"Name"}=~/\*/
14627 or $Type2_Pure{"Name"}=~/\*/)
14628 { # compared in detectTypeChange()
14629 return 0;
14630 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014631
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014632 my %FloatType = map {$_=>1} (
14633 "float",
14634 "double",
14635 "long double"
14636 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014637
14638 my $T1 = $Type1_Pure{"Type"};
14639 my $T2 = $Type2_Pure{"Type"};
14640
14641 if($T1 eq "Struct"
14642 and $T2 eq "Class")
14643 { # compare as data structures
14644 $T2 = "Struct";
14645 }
14646
14647 if($T1 eq "Class"
14648 and $T2 eq "Struct")
14649 { # compare as data structures
14650 $T1 = "Struct";
14651 }
14652
14653 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014654 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014655 if($T1 eq "Intrinsic"
14656 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014657 { # "int" to "enum"
14658 return 0;
14659 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014660 elsif($T2 eq "Intrinsic"
14661 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014662 { # "enum" to "int"
14663 return 0;
14664 }
14665 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014666 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014667 # ...
14668 return 1;
14669 }
14670 }
14671 else
14672 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014673 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 {
14675 if($FloatType{$Type1_Pure{"Name"}}
14676 or $FloatType{$Type2_Pure{"Name"}})
14677 { # "float" to "double"
14678 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014679 if($Level eq "Source")
14680 { # Safe
14681 return 0;
14682 }
14683 else {
14684 return 1;
14685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 }
14687 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014688 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014689 {
14690 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14691 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014692 if(not @Membs1
14693 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014694 { # private
14695 return 0;
14696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014697 if($#Membs1!=$#Membs2)
14698 { # different number of elements
14699 return 1;
14700 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014701 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014702 {
14703 foreach my $Pos (@Membs1)
14704 { # compare elements by name and value
14705 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14706 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14707 { # different names
14708 return 1;
14709 }
14710 }
14711 }
14712 else
14713 {
14714 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014715 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014716 if($Level eq "Source")
14717 {
14718 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14719 { # different names
14720 return 1;
14721 }
14722 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014723
14724 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14725 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14726
14727 if($MT1{"Name"} ne $MT2{"Name"}
14728 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14729 {
14730 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14731 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14732
14733 if($PL1 ne $PL2)
14734 { # different pointer level
14735 return 1;
14736 }
14737
14738 # compare base types
14739 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14740 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14741
14742 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14743 { # different types
14744 return 1;
14745 }
14746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014747 }
14748 }
14749 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014750 else
14751 {
14752 # TODO: arrays, etc.
14753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014754 }
14755 return 0;
14756}
14757
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014758sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014759{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014760 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014761 if(not $Type1_Id or not $Type2_Id) {
14762 return ();
14763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014764 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014765 my %Type1 = get_Type($Type1_Id, 1);
14766 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014767 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14768 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014769
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014770 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14771 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 +040014772
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014773 if(defined $UsedDump{1}{"DWARF"})
14774 {
14775 if($Type1_Pure{"Name"} eq "__unknown__"
14776 or $Type2_Pure{"Name"} eq "__unknown__"
14777 or $Type1_Base{"Name"} eq "__unknown__"
14778 or $Type2_Base{"Name"} eq "__unknown__")
14779 { # Error ABI dump
14780 return ();
14781 }
14782 }
14783
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014784 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14785 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014786 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14787 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14788 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14789 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14790 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14791 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14792 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014793 if($Type1{"Name"} eq $Type2{"Name"})
14794 {
14795 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14796 { # will be reported in mergeTypes() as typedef problem
14797 return ();
14798 }
14799 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14800 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14801 if(%Typedef_1 and %Typedef_2)
14802 {
14803 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14804 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14805 { # const Typedef
14806 return ();
14807 }
14808 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014809 }
14810 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14811 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014812 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014813 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14814 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014815 {
14816 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14817 "Old_Value"=>$Type1_Base{"Name"},
14818 "New_Value"=>$Type2_Base{"Name"},
14819 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014820 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014821 }
14822 else
14823 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014824 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014825 { # format change
14826 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14827 "Old_Value"=>$Type1_Base{"Name"},
14828 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014829 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014830 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014831 }
14832 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14833 {
14834 %{$LocalProblems{$Prefix."_BaseType"}}=(
14835 "Old_Value"=>$Type1_Base{"Name"},
14836 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014837 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014838 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014839 }
14840 }
14841 }
14842 }
14843 elsif($Type1{"Name"} ne $Type2{"Name"})
14844 { # type change
14845 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14846 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014847 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014848 and $Type1_Pure{"Name"} eq "void")
14849 {
14850 %{$LocalProblems{"Return_Type_From_Void"}}=(
14851 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014852 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014854 elsif($Prefix eq "Return"
14855 and $Type2_Pure{"Name"} eq "void")
14856 {
14857 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14858 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014859 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014861 else
14862 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014863 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014864 and $Type1{"Size"} and $Type2{"Size"}
14865 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014866 {
14867 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14868 "Old_Value"=>$Type1{"Name"},
14869 "New_Value"=>$Type2{"Name"},
14870 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014871 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014872 }
14873 else
14874 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014875 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014876 { # format change
14877 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14878 "Old_Value"=>$Type1{"Name"},
14879 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014880 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014881 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014882 }
14883 elsif(tNameLock($Type1_Id, $Type2_Id))
14884 { # FIXME: correct this condition
14885 %{$LocalProblems{$Prefix."_Type"}}=(
14886 "Old_Value"=>$Type1{"Name"},
14887 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014888 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014889 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014890 }
14891 }
14892 }
14893 }
14894 }
14895 if($Type1_PLevel!=$Type2_PLevel)
14896 {
14897 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14898 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14899 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014900 if($Level eq "Source")
14901 {
14902 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014903 "Old_Value"=>$Type1_PLevel,
14904 "New_Value"=>$Type2_PLevel);
14905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014906 else
14907 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014908 if($Type2_PLevel>$Type1_PLevel)
14909 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014910 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14911 "Old_Value"=>$Type1_PLevel,
14912 "New_Value"=>$Type2_PLevel);
14913 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014914 else
14915 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014916 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14917 "Old_Value"=>$Type1_PLevel,
14918 "New_Value"=>$Type2_PLevel);
14919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 }
14921 }
14922 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014923 if($Type1_Pure{"Type"} eq "Array"
14924 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014925 { # base_type[N] -> base_type[N]
14926 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014927 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014928 foreach my $SubProblemType (keys(%SubProblems))
14929 {
14930 $SubProblemType=~s/_Type/_BaseType/g;
14931 next if(defined $LocalProblems{$SubProblemType});
14932 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14933 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14934 }
14935 }
14936 }
14937 return %LocalProblems;
14938}
14939
14940sub tNameLock($$)
14941{
14942 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014943 my $Changed = 0;
14944 if(differentDumps("G"))
14945 { # different GCC versions
14946 $Changed = 1;
14947 }
14948 elsif(differentDumps("V"))
14949 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014950 if(not checkDump(1, "2.20")
14951 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014952 { # latest names update
14953 # 2.6: added restrict qualifier
14954 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014955 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014956 $Changed = 1;
14957 }
14958 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014959
14960 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14961 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14962
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014963 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14964 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14965
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014966 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014967 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014968 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014969 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014970 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014971 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014972 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014973 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014974 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014975 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014976 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14977 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14978 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 { # equal base types
14980 return 0;
14981 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014982
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014983 if(not checkDump(1, "2.13")
14984 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014985 { # broken array names in ABI dumps < 2.13
14986 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014987 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014988 return 0;
14989 }
14990 }
14991
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014992 if(not checkDump(1, "2.6")
14993 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014994 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014995 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014996 and $TN2=~/\brestrict\b/) {
14997 return 0;
14998 }
14999 }
15000
15001 if(not checkDump(1, "2.20")
15002 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015003 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015004 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15005 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015006 return 0;
15007 }
15008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015010 else
15011 {
15012 # typedef struct {...} type_t
15013 # typedef struct type_t {...} type_t
15014 if(index($TN1, " ".$TN2)!=-1)
15015 {
15016 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15017 return 0;
15018 }
15019 }
15020 if(index($TN2, " ".$TN1)!=-1)
15021 {
15022 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15023 return 0;
15024 }
15025 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015026
15027 if($TT1 eq "FuncPtr"
15028 and $TT2 eq "FuncPtr")
15029 {
15030 my $TN1_C = $TN1;
15031 my $TN2_C = $TN2;
15032
15033 $TN1_C=~s/\b(struct|union) //g;
15034 $TN2_C=~s/\b(struct|union) //g;
15035
15036 if($TN1_C eq $TN2_C) {
15037 return 0;
15038 }
15039 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015040 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015041
15042 my ($N1, $N2) = ($TN1, $TN2);
15043 $N1=~s/\b(struct|union) //g;
15044 $N2=~s/\b(struct|union) //g;
15045
15046 if($N1 eq $N2)
15047 { # QList<struct QUrl> and QList<QUrl>
15048 return 0;
15049 }
15050
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015051 return 1;
15052}
15053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015054sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015055{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015056 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015057 if(defined $Cache{"differentDumps"}{$Check}) {
15058 return $Cache{"differentDumps"}{$Check};
15059 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015060 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015061 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015062 if($Check eq "G")
15063 {
15064 if(getGccVersion(1) ne getGccVersion(2))
15065 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015066 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015068 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015069 if($Check eq "V")
15070 {
15071 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15072 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15073 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015074 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015077 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015078 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015079}
15080
15081sub formatVersion($$)
15082{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015083 my ($V, $Digits) = @_;
15084 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015085 return join(".", splice(@Elems, 0, $Digits));
15086}
15087
15088sub htmlSpecChars($)
15089{
15090 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015091 if(not $Str) {
15092 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015094 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15095 $Str=~s/</&lt;/g;
15096 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15097 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015098 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15099 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015100 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015101 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015102 $Str=~s/\n/<br\/>/g;
15103 $Str=~s/\"/&quot;/g;
15104 $Str=~s/\'/&#39;/g;
15105 return $Str;
15106}
15107
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015108sub xmlSpecChars($)
15109{
15110 my $Str = $_[0];
15111 if(not $Str) {
15112 return $Str;
15113 }
15114
15115 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15116 $Str=~s/</&lt;/g;
15117 $Str=~s/>/&gt;/g;
15118
15119 $Str=~s/\"/&quot;/g;
15120 $Str=~s/\'/&#39;/g;
15121
15122 return $Str;
15123}
15124
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015125sub xmlSpecChars_R($)
15126{
15127 my $Str = $_[0];
15128 if(not $Str) {
15129 return $Str;
15130 }
15131
15132 $Str=~s/&amp;/&/g;
15133 $Str=~s/&lt;/</g;
15134 $Str=~s/&gt;/>/g;
15135
15136 $Str=~s/&quot;/"/g;
15137 $Str=~s/&#39;/'/g;
15138
15139 return $Str;
15140}
15141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015142sub black_name($)
15143{
15144 my $Name = $_[0];
15145 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15146}
15147
15148sub highLight_Signature($)
15149{
15150 my $Signature = $_[0];
15151 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15152}
15153
15154sub highLight_Signature_Italic_Color($)
15155{
15156 my $Signature = $_[0];
15157 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15158}
15159
15160sub separate_symbol($)
15161{
15162 my $Symbol = $_[0];
15163 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15164 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15165 ($Name, $Spec, $Ver) = ($1, $2, $3);
15166 }
15167 return ($Name, $Spec, $Ver);
15168}
15169
15170sub cut_f_attrs($)
15171{
15172 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15173 return $2;
15174 }
15175 return "";
15176}
15177
15178sub highLight_Signature_PPos_Italic($$$$$)
15179{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015180 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15181 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015182 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15183 my $Return = "";
15184 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15185 $Return = $2;
15186 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015187 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015188 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015189 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015190 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015191 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015192 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015193 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015194 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195 }
15196 return $Signature;
15197 }
15198 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15199 $Begin.=" " if($Begin!~/ \Z/);
15200 $End = cut_f_attrs($Signature);
15201 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015202 my ($Short, $Params) = split_Signature($Signature);
15203 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015204 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015206 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015207 $Part=~s/\A\s+|\s+\Z//g;
15208 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15209 if($Part=~/\([\*]+(\w+)\)/i) {
15210 $ParamName = $1;#func-ptr
15211 }
15212 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15213 $ParamName = $1;
15214 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015215 if(not $ParamName)
15216 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015217 push(@Parts, $Part_Styled);
15218 next;
15219 }
15220 if($ItalicParams and not $TName_Tid{1}{$Part}
15221 and not $TName_Tid{2}{$Part})
15222 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015223 my $Style = "<i>$ParamName</i>";
15224
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015225 if($Param_Pos ne ""
15226 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015227 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015228 }
15229 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015230 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015232
15233 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 }
15235 $Part_Styled=~s/,(\w)/, $1/g;
15236 push(@Parts, $Part_Styled);
15237 }
15238 if(@Parts)
15239 {
15240 foreach my $Num (0 .. $#Parts)
15241 {
15242 if($Num==$#Parts)
15243 { # add ")" to the last parameter
15244 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15245 }
15246 elsif(length($Parts[$Num])<=45) {
15247 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15248 }
15249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015250 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015251 }
15252 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015253 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015254 }
15255 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015256 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015258 $Signature=~s!\[\]![&#160;]!g;
15259 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015260 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15261 if($SymbolVersion) {
15262 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15263 }
15264 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015265}
15266
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015267sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015269 my $Signature = $_[0];
15270 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15271 {
15272 $Signature=~s/\A\Q$ShortName\E\(//g;
15273 cut_f_attrs($Signature);
15274 $Signature=~s/\)\Z//;
15275 return ($ShortName, $Signature);
15276 }
15277
15278 # error
15279 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015280}
15281
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015282sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015283{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015284 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015285 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015286 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15287 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 foreach my $Pos (0 .. length($Params) - 1)
15289 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015290 my $S = substr($Params, $Pos, 1);
15291 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015292 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015293 }
15294 if($S eq "," and
15295 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015297 if($Comma)
15298 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015299 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015301 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015302 }
15303 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015304 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015305 }
15306 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015307 if(not $Sp)
15308 { # remove spaces
15309 foreach (@Parts)
15310 {
15311 s/\A //g;
15312 s/ \Z//g;
15313 }
15314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015315 return @Parts;
15316}
15317
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015318sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015319{
15320 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015321 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015323 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15324 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015325 $Center+=length($1);
15326 }
15327 foreach my $Pos (0 .. length($Sign)-1)
15328 {
15329 my $S = substr($Sign, $Pos, 1);
15330 if($S eq $Target)
15331 {
15332 if($B{"("}==$B{")"}
15333 and $B{"<"}==$B{">"}) {
15334 return $Center;
15335 }
15336 }
15337 if(defined $B{$S}) {
15338 $B{$S}+=1;
15339 }
15340 $Center+=1;
15341 }
15342 return 0;
15343}
15344
15345sub appendFile($$)
15346{
15347 my ($Path, $Content) = @_;
15348 return if(not $Path);
15349 if(my $Dir = get_dirname($Path)) {
15350 mkpath($Dir);
15351 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015352 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015353 print FILE $Content;
15354 close(FILE);
15355}
15356
15357sub writeFile($$)
15358{
15359 my ($Path, $Content) = @_;
15360 return if(not $Path);
15361 if(my $Dir = get_dirname($Path)) {
15362 mkpath($Dir);
15363 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015364 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015365 print FILE $Content;
15366 close(FILE);
15367}
15368
15369sub readFile($)
15370{
15371 my $Path = $_[0];
15372 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015373 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015374 local $/ = undef;
15375 my $Content = <FILE>;
15376 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015377 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015378 $Content=~s/\r/\n/g;
15379 }
15380 return $Content;
15381}
15382
15383sub get_filename($)
15384{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015385 if(defined $Cache{"get_filename"}{$_[0]}) {
15386 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015387 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015388 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15389 return ($Cache{"get_filename"}{$_[0]}=$1);
15390 }
15391 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015392}
15393
15394sub get_dirname($)
15395{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015396 if(defined $Cache{"get_dirname"}{$_[0]}) {
15397 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015399 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15400 return ($Cache{"get_dirname"}{$_[0]}=$1);
15401 }
15402 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403}
15404
15405sub separate_path($) {
15406 return (get_dirname($_[0]), get_filename($_[0]));
15407}
15408
15409sub esc($)
15410{
15411 my $Str = $_[0];
15412 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15413 return $Str;
15414}
15415
15416sub readLineNum($$)
15417{
15418 my ($Path, $Num) = @_;
15419 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015420 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421 foreach (1 ... $Num) {
15422 <FILE>;
15423 }
15424 my $Line = <FILE>;
15425 close(FILE);
15426 return $Line;
15427}
15428
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015429sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015430{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015431 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015432 return () if(not $Path or not -f $Path);
15433 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015434 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15435 {
15436 foreach my $AttrVal (split(/;/, $1))
15437 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015438 if($AttrVal=~/(.+):(.+)/)
15439 {
15440 my ($Name, $Value) = ($1, $2);
15441 $Attributes{$Name} = $Value;
15442 }
15443 }
15444 }
15445 return \%Attributes;
15446}
15447
15448sub is_abs($) {
15449 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15450}
15451
15452sub get_abs_path($)
15453{ # abs_path() should NOT be called for absolute inputs
15454 # because it can change them
15455 my $Path = $_[0];
15456 if(not is_abs($Path)) {
15457 $Path = abs_path($Path);
15458 }
15459 return $Path;
15460}
15461
15462sub get_OSgroup()
15463{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015464 my $N = $Config{"osname"};
15465 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015466 return "macos";
15467 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015468 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015469 return "bsd";
15470 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015471 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015472 return "beos";
15473 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015474 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 return "symbian";
15476 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015477 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 return "windows";
15479 }
15480 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015481 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482 }
15483}
15484
15485sub getGccVersion($)
15486{
15487 my $LibVersion = $_[0];
15488 if($GCC_VERSION{$LibVersion})
15489 { # dump version
15490 return $GCC_VERSION{$LibVersion};
15491 }
15492 elsif($UsedDump{$LibVersion}{"V"})
15493 { # old-version dumps
15494 return "unknown";
15495 }
15496 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15497 if(not $GccVersion) {
15498 return "unknown";
15499 }
15500 return $GccVersion;
15501}
15502
15503sub showArch($)
15504{
15505 my $Arch = $_[0];
15506 if($Arch eq "arm"
15507 or $Arch eq "mips") {
15508 return uc($Arch);
15509 }
15510 return $Arch;
15511}
15512
15513sub getArch($)
15514{
15515 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015516
15517 if($TargetArch) {
15518 return $TargetArch;
15519 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015520 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015521 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015522 return $CPU_ARCH{$LibVersion};
15523 }
15524 elsif($UsedDump{$LibVersion}{"V"})
15525 { # old-version dumps
15526 return "unknown";
15527 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015528
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015529 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015530}
15531
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015532sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015533{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015534 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015535
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015536 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015537 if(getArch(1) ne getArch(2)
15538 or getArch(1) eq "unknown"
15539 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015540 { # don't show architecture in the header
15541 $ArchInfo="";
15542 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015543 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015544 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015545 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015546 }
15547 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015548 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015549 }
15550 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015551 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015552 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015553
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015554 my $V1 = $Descriptor{1}{"Version"};
15555 my $V2 = $Descriptor{2}{"Version"};
15556
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015557 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15558 {
15559 my $M1 = $UsedDump{1}{"M"};
15560 my $M2 = $UsedDump{2}{"M"};
15561
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015562 my $M1S = $M1;
15563 my $M2S = $M2;
15564
15565 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15566 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15567
15568 if($M1S eq $M2S
15569 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015570 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015571 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15572 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015573 }
15574 else
15575 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015576 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15577 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015578 }
15579 }
15580 else
15581 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015582 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015583 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015584 }
15585
15586 $Title .= $ArchInfo;
15587
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015588 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015589 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015591 $Title = "<h1>".$Title."</h1>\n";
15592 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593}
15594
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015595sub get_CheckedHeaders($)
15596{
15597 my $LibVersion = $_[0];
15598
15599 my @Headers = ();
15600
15601 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15602 {
15603 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015604
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015605 if(not is_target_header($File, $LibVersion)) {
15606 next;
15607 }
15608
15609 if(skipHeader($File, $LibVersion)) {
15610 next;
15611 }
15612
15613 push(@Headers, $Path);
15614 }
15615
15616 return @Headers;
15617}
15618
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619sub get_SourceInfo()
15620{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015621 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015622
15623 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015624 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015625 $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 +030015626 $CheckedHeaders .= "<div class='h_list'>\n";
15627 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 +040015628 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015629 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15630 my $Name = get_filename($Identity);
15631 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15632 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015633 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015634 $CheckedHeaders .= "</div>\n";
15635 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015636 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015637
15638 if(my @Sources = keys(%{$Registered_Sources{1}}))
15639 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015640 $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 +030015641 $CheckedSources .= "<div class='h_list'>\n";
15642 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15643 {
15644 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15645 my $Name = get_filename($Identity);
15646 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15647 $CheckedSources .= $Name.$Comment."<br/>\n";
15648 }
15649 $CheckedSources .= "</div>\n";
15650 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15651 }
15652
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015653 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015654 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015655 $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 +040015656 $CheckedLibs .= "<div class='lib_list'>\n";
15657 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15658 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015659 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015660 $CheckedLibs .= $Library."<br/>\n";
15661 }
15662 $CheckedLibs .= "</div>\n";
15663 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015664 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015665
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015666 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15667}
15668
15669sub get_ObjTitle()
15670{
15671 if(defined $UsedDump{1}{"DWARF"}) {
15672 return "Objects";
15673 }
15674 else {
15675 return ucfirst($SLIB_TYPE)." Libraries";
15676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015677}
15678
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015679sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015680{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015681 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015682 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015683
15684 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015685 {
15686 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015687 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015688 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015689 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015691 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015692 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015693
15694 if($Severity ne $TargetSeverity) {
15695 next;
15696 }
15697
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015698 if($Kinds_Target{$Kind}{$Target}) {
15699 next;
15700 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015701
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015702 $Kinds_Target{$Kind}{$Target} = 1;
15703 $Type_Problems_Count += 1;
15704 }
15705 }
15706 }
15707 return $Type_Problems_Count;
15708}
15709
15710sub get_Summary($)
15711{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015712 my $Level = $_[0];
15713 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015714 $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 +040015715 %{$RESULT{$Level}} = (
15716 "Problems"=>0,
15717 "Warnings"=>0,
15718 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015719 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015720 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015722 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015723 {
15724 if(not defined $CompatRules{$Level}{$Kind})
15725 { # unknown rule
15726 if(not $UnknownRules{$Level}{$Kind})
15727 { # only one warning
15728 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15729 $UnknownRules{$Level}{$Kind}=1;
15730 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015731 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015732 }
15733 }
15734 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015735 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15736 {
15737 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15738 {
15739 if(not defined $CompatRules{$Level}{$Kind})
15740 { # unknown rule
15741 if(not $UnknownRules{$Level}{$Kind})
15742 { # only one warning
15743 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15744 $UnknownRules{$Level}{$Kind}=1;
15745 }
15746 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15747 }
15748 }
15749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015750 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015751 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015752 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015753 {
15754 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15755 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015756 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015757 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015758 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 $Added += 1;
15761 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015762 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015763 {
15764 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015765 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015766 }
15767 else
15768 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015769 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 $I_Other += 1;
15771 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015772 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015773 $I_Problems_High += 1;
15774 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015775 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015776 $I_Problems_Medium += 1;
15777 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015778 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015779 $I_Problems_Low += 1;
15780 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015781 if(($Severity ne "Low" or $StrictCompat)
15782 and $Severity ne "Safe") {
15783 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015784 }
15785 }
15786 }
15787 }
15788 }
15789 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015790
15791 my %MethodTypeIndex = ();
15792
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015793 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015794 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015795 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15796 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015797 {
15798 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15799 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015800 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15801 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015802 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015803 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15804 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015805
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015806 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15807 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808 next;
15809 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015810 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15811 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15812
15813 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015814
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015815 if(($Severity ne "Low" or $StrictCompat)
15816 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015817 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015818 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015819 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015820 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015821 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015822 }
15823 }
15824 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015825 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015828 }
15829 }
15830 }
15831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015832
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015833 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15834 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15835 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15836 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015837
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015838 # changed and removed public symbols
15839 my $SCount = keys(%{$CheckedSymbols{$Level}});
15840 if($ExtendedCheck)
15841 { # don't count external_func_0 for constants
15842 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015843 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015844 if($SCount)
15845 {
15846 my %Weight = (
15847 "High" => 100,
15848 "Medium" => 50,
15849 "Low" => 25
15850 );
15851 foreach (keys(%{$TotalAffected{$Level}})) {
15852 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015854 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015855 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015856 else {
15857 $RESULT{$Level}{"Affected"} = 0;
15858 }
15859
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015860 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15861 if($RESULT{$Level}{"Affected"}>=100) {
15862 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015863 }
15864
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015865 $RESULT{$Level}{"Problems"} += $Removed;
15866 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015867 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015868 if($StrictCompat) {
15869 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15870 }
15871 else {
15872 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015874
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015875 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015876 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015877 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015878 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015879 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015880 if($Severity eq "Safe")
15881 {
15882 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015883 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015884 elsif($Severity eq "Low")
15885 {
15886 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015888 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015889 }
15890
15891 if($C_Problems_Low)
15892 {
15893 if($StrictCompat) {
15894 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15895 }
15896 else {
15897 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015898 }
15899 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015900 if($RESULT{$Level}{"Problems"}
15901 and $RESULT{$Level}{"Affected"}) {
15902 $RESULT{$Level}{"Verdict"} = "incompatible";
15903 }
15904 else {
15905 $RESULT{$Level}{"Verdict"} = "compatible";
15906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015907
15908 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15909 if(not $TotalTypes)
15910 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015911 $TotalTypes = keys(%{$TName_Tid{1}});
15912 }
15913
15914 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15915 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15916
15917 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15918
15919 if($ReportFormat eq "xml")
15920 { # XML
15921 # test info
15922 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15923 $TestInfo .= " <version1>\n";
15924 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015925 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015926 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15927 $TestInfo .= " </version1>\n";
15928
15929 $TestInfo .= " <version2>\n";
15930 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015931 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015932 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15933 $TestInfo .= " </version2>\n";
15934 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15935
15936 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015937 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015938 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015939 $TestResults .= " <headers>\n";
15940 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15941 {
15942 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15943 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15944 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15945 }
15946 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015947 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015948
15949 if(my @Sources = keys(%{$Registered_Sources{1}}))
15950 {
15951 $TestResults .= " <sources>\n";
15952 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15953 {
15954 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15955 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15956 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15957 }
15958 $TestResults .= " </sources>\n";
15959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015960
15961 $TestResults .= " <libs>\n";
15962 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15963 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015964 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015965 $TestResults .= " <name>$Library</name>\n";
15966 }
15967 $TestResults .= " </libs>\n";
15968
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015969 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015970 $TestResults .= " <types>".$TotalTypes."</types>\n";
15971
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015972 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15973 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015974 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15975
15976 # problem summary
15977 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15978 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15979
15980 $Problem_Summary .= " <problems_with_types>\n";
15981 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15982 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15983 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15984 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15985 $Problem_Summary .= " </problems_with_types>\n";
15986
15987 $Problem_Summary .= " <problems_with_symbols>\n";
15988 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15989 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15990 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015991 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015992 $Problem_Summary .= " </problems_with_symbols>\n";
15993
15994 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015996 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015997
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015998 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15999
16000 return ($TestInfo.$TestResults.$Problem_Summary, "");
16001 }
16002 else
16003 { # HTML
16004 # test info
16005 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016006 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016007
16008 if($TargetComponent eq "library") {
16009 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16010 }
16011 else {
16012 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016014
16015 my (@VInf1, @VInf2, $AddTestInfo) = ();
16016 if($Arch1 ne "unknown"
16017 and $Arch2 ne "unknown")
16018 { # CPU arch
16019 if($Arch1 eq $Arch2)
16020 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016021 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022 }
16023 else
16024 { # go to the version number
16025 push(@VInf1, showArch($Arch1));
16026 push(@VInf2, showArch($Arch2));
16027 }
16028 }
16029 if($GccV1 ne "unknown"
16030 and $GccV2 ne "unknown"
16031 and $OStarget ne "windows")
16032 { # GCC version
16033 if($GccV1 eq $GccV2)
16034 { # go to the separate section
16035 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16036 }
16037 else
16038 { # go to the version number
16039 push(@VInf1, "gcc ".$GccV1);
16040 push(@VInf2, "gcc ".$GccV2);
16041 }
16042 }
16043 # show long version names with GCC version and CPU architecture name (if different)
16044 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16045 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16046 $TestInfo .= $AddTestInfo;
16047 #if($COMMON_LANGUAGE{1}) {
16048 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16049 #}
16050 if($ExtendedCheck) {
16051 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16052 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016053 if($JoinReport)
16054 {
16055 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016056 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016057 }
16058 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016059 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016060 }
16061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016062 $TestInfo .= "</table>\n";
16063
16064 # test results
16065 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016066 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016067
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016068 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016069 {
16070 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16071 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16072 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016073
16074 if(my @Sources = keys(%{$Registered_Sources{1}}))
16075 {
16076 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16077 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016079
16080 if(not $ExtendedCheck)
16081 {
16082 my $Libs_Link = "0";
16083 $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 +040016084 $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 +040016085 }
16086
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016087 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016088
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016089 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016090 if($JoinReport) {
16091 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16092 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016093
16094 my $BC_Rate = 100 - $RESULT{$Level}{"Affected"};
16095
16096 $TestResults .= "<tr><th>Compatibility</th>\n";
16097 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16098 {
16099 my $Cl = "incompatible";
16100 if($BC_Rate>=90) {
16101 $Cl = "warning";
16102 }
16103 elsif($BC_Rate>=80) {
16104 $Cl = "almost_compatible";
16105 }
16106
16107 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016108 }
16109 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016110 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016111 }
16112 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016113 $TestResults .= "</table>\n";
16114
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016115 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016116 # problem summary
16117 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016118 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016119 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16120
16121 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016122 if($Added>0)
16123 {
16124 if($JoinReport) {
16125 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16126 }
16127 else {
16128 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16129 }
16130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016131 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016132 $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 +040016133
16134 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016135 if($Removed>0)
16136 {
16137 if($JoinReport) {
16138 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16139 }
16140 else {
16141 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16142 }
16143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016144 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016145 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016146 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016147
16148 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016149 $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 +040016150 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016151 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016152 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016153
16154 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016155 $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 +040016156 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016157 $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 +040016158
16159 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016160 $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 +040016161 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016162 $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 +040016163
16164 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016165 $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 +040016166 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016167 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016168 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016169
16170 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016171 $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 +040016172 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016173 $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 +040016174
16175 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016176 $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 +040016177 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016178 $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 +040016179
16180 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016181 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16182 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016185 $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 +040016186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016188 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016189 {
16190 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016191 $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 +030016192 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016194
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016195 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016196 {
16197 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016198 $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 +030016199 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016201
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016202 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016203 {
16204 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016205 $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 +030016206 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016207 }
16208
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016209 $META_DATA .= "tool_version:$TOOL_VERSION";
16210 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016211
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016212 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16213 }
16214}
16215
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016216sub getStyle($$$)
16217{
16218 my ($Subj, $Act, $Num) = @_;
16219 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016220 "Added"=>"new",
16221 "Removed"=>"failed",
16222 "Safe"=>"passed",
16223 "Low"=>"warning",
16224 "Medium"=>"failed",
16225 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016226 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016227
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016228 if($Num>0) {
16229 return " class='".$Style{$Act}."'";
16230 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016231
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016232 return "";
16233}
16234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016235sub show_number($)
16236{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016237 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016238 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016239 my $Num = cut_off_number($_[0], 2, 0);
16240 if($Num eq "0")
16241 {
16242 foreach my $P (3 .. 7)
16243 {
16244 $Num = cut_off_number($_[0], $P, 1);
16245 if($Num ne "0") {
16246 last;
16247 }
16248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016249 }
16250 if($Num eq "0") {
16251 $Num = $_[0];
16252 }
16253 return $Num;
16254 }
16255 return $_[0];
16256}
16257
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016258sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016260 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261 if($num!~/\./)
16262 {
16263 $num .= ".";
16264 foreach (1 .. $digs_to_cut-1) {
16265 $num .= "0";
16266 }
16267 }
16268 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16269 {
16270 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16271 $num .= "0";
16272 }
16273 }
16274 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16275 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16276 }
16277 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016278 if($z) {
16279 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016281 return $num;
16282}
16283
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016284sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016285{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016286 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016287 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016288
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016289 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016290 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16291 {
16292 my $Header = $Constants{1}{$Constant}{"Header"};
16293 if(not $Header)
16294 { # added
16295 $Header = $Constants{2}{$Constant}{"Header"}
16296 }
16297
16298 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16299 {
16300 if(not defined $CompatRules{$Level}{$Kind}) {
16301 next;
16302 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016303 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016304 next;
16305 }
16306 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016309
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310 if($ReportFormat eq "xml")
16311 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016312 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016313 {
16314 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016315 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016316 {
16317 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016318 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16319 {
16320 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16321 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16322 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016323
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016324 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16325 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16326 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016327 if($Overcome) {
16328 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16329 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016330 $CHANGED_CONSTANTS .= " </problem>\n";
16331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016332 $CHANGED_CONSTANTS .= " </constant>\n";
16333 }
16334 $CHANGED_CONSTANTS .= " </header>\n";
16335 }
16336 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16337 }
16338 else
16339 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016340 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016341 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 {
16343 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016344 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016346 my $Report = "";
16347
16348 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16349 {
16350 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16351 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016352 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016353 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016354 }
16355 if($Report)
16356 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016357 $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 +030016358 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016359 $Report = insertIDs($Report);
16360 }
16361 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016362 }
16363 $CHANGED_CONSTANTS .= "<br/>\n";
16364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016365 if($CHANGED_CONSTANTS)
16366 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016367 my $Title = "Problems with Constants, $TargetSeverity Severity";
16368 if($TargetSeverity eq "Safe")
16369 { # Safe Changes
16370 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016371 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016372 $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 +040016373 }
16374 }
16375 return $CHANGED_CONSTANTS;
16376}
16377
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378sub getTitle($$$)
16379{
16380 my ($Header, $Library, $NameSpace) = @_;
16381 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016382
16383 # if($Library and $Library!~/\.\w+\Z/) {
16384 # $Library .= " (.$LIB_EXT)";
16385 # }
16386
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016387 if($Header and $Library)
16388 {
16389 $Title .= "<span class='h_name'>$Header</span>";
16390 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16391 }
16392 elsif($Library) {
16393 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16394 }
16395 elsif($Header) {
16396 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16397 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016398
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016399 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016400 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016401 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016402
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016403 return $Title;
16404}
16405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406sub get_Report_Added($)
16407{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016408 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016409 my $ADDED_INTERFACES = "";
16410 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016411 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016412 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016413 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016414 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016415 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016416 {
16417 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16418 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016419 if($Level eq "Source" and $ReportFormat eq "html")
16420 { # do not show library name in HTML report
16421 $DyLib = "";
16422 }
16423 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016424 }
16425 }
16426 }
16427 if($ReportFormat eq "xml")
16428 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016429 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016430 {
16431 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016433 {
16434 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016435 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016436 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16437 }
16438 $ADDED_INTERFACES .= " </library>\n";
16439 }
16440 $ADDED_INTERFACES .= " </header>\n";
16441 }
16442 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16443 }
16444 else
16445 { # HTML
16446 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016447 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016448 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016449 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016450 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016451 my %NameSpaceSymbols = ();
16452 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016453 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016454 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016455 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016456 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016457 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16458 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 foreach my $Interface (@SortedInterfaces)
16460 {
16461 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 my $Signature = get_Signature($Interface, 2);
16463 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016464 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016466 if($Interface=~/\A(_Z|\?)/)
16467 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016468 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016469 $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 +040016470 }
16471 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016472 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473 }
16474 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016475 else
16476 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016477 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016478 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 }
16480 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016481 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016482 }
16483 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016485 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 }
16488 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016489 if($ADDED_INTERFACES)
16490 {
16491 my $Anchor = "<a name='Added'></a>";
16492 if($JoinReport) {
16493 $Anchor = "<a name='".$Level."_Added'></a>";
16494 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016495 $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 +040016496 }
16497 }
16498 return $ADDED_INTERFACES;
16499}
16500
16501sub get_Report_Removed($)
16502{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016503 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016504 my $REMOVED_INTERFACES = "";
16505 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016506 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016507 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016508 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016509 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016510 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016512 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16513 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 if($Level eq "Source" and $ReportFormat eq "html")
16515 { # do not show library name in HTML report
16516 $DyLib = "";
16517 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016518 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016519 }
16520 }
16521 }
16522 if($ReportFormat eq "xml")
16523 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016524 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 {
16526 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016527 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 {
16529 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016530 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16531 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016532 }
16533 $REMOVED_INTERFACES .= " </library>\n";
16534 }
16535 $REMOVED_INTERFACES .= " </header>\n";
16536 }
16537 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16538 }
16539 else
16540 { # HTML
16541 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016542 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016543 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016544 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016545 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016546 my %NameSpaceSymbols = ();
16547 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016548 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016549 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016550 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016551 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016552 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16553 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016554 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016555 {
16556 $Removed_Number += 1;
16557 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016558 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016559 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016560 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016561 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016562 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016563 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016564 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016565 $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 +040016566 }
16567 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016568 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016569 }
16570 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016571 else
16572 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016573 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016574 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016575 }
16576 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016577 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 }
16579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 }
16581 }
16582 $REMOVED_INTERFACES .= "<br/>\n";
16583 }
16584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 if($REMOVED_INTERFACES)
16586 {
16587 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16588 if($JoinReport) {
16589 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16590 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016591 $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 +040016592 }
16593 }
16594 return $REMOVED_INTERFACES;
16595}
16596
16597sub getXmlParams($$)
16598{
16599 my ($Content, $Problem) = @_;
16600 return "" if(not $Content or not $Problem);
16601 my %XMLparams = ();
16602 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16603 {
16604 my $Macro = "\@".lc($Attr);
16605 if($Content=~/\Q$Macro\E/) {
16606 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16607 }
16608 }
16609 my @PString = ();
16610 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016611 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016612 }
16613 if(@PString) {
16614 return " ".join(" ", @PString);
16615 }
16616 else {
16617 return "";
16618 }
16619}
16620
16621sub addMarkup($)
16622{
16623 my $Content = $_[0];
16624 # auto-markup
16625 $Content=~s/\n[ ]*//; # spaces
16626 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16627 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016628 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16630 if($Content=~/\ANOTE:/)
16631 { # notes
16632 $Content=~s!(NOTE):!<b>$1</b>:!g;
16633 }
16634 else {
16635 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16636 }
16637 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16638 my @Keywords = (
16639 "void",
16640 "const",
16641 "static",
16642 "restrict",
16643 "volatile",
16644 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016645 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 );
16647 my $MKeys = join("|", @Keywords);
16648 foreach (@Keywords) {
16649 $MKeys .= "|non-".$_;
16650 }
16651 $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 +040016652
16653 # Markdown
16654 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16655 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016656 return $Content;
16657}
16658
16659sub applyMacroses($$$$)
16660{
16661 my ($Level, $Kind, $Content, $Problem) = @_;
16662 return "" if(not $Content or not $Problem);
16663 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16664 $Content = addMarkup($Content);
16665 # macros
16666 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16667 {
16668 my $Macro = "\@".lc($Attr);
16669 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016670 if(not defined $Value
16671 or $Value eq "") {
16672 next;
16673 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016674
16675 if(index($Content, $Macro)==-1) {
16676 next;
16677 }
16678
16679 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16680 and $Kind!~/_Type_/
16681 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016683 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016684 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 $Value = black_name($Value);
16686 }
16687 elsif($Value=~/\s/) {
16688 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16689 }
16690 elsif($Value=~/\A\d+\Z/
16691 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16692 { # bits to bytes
16693 if($Value % $BYTE_SIZE)
16694 { # bits
16695 if($Value==1) {
16696 $Value = "<b>".$Value."</b> bit";
16697 }
16698 else {
16699 $Value = "<b>".$Value."</b> bits";
16700 }
16701 }
16702 else
16703 { # bytes
16704 $Value /= $BYTE_SIZE;
16705 if($Value==1) {
16706 $Value = "<b>".$Value."</b> byte";
16707 }
16708 else {
16709 $Value = "<b>".$Value."</b> bytes";
16710 }
16711 }
16712 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016713 else
16714 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016715 $Value = "<b>".htmlSpecChars($Value)."</b>";
16716 }
16717 $Content=~s/\Q$Macro\E/$Value/g;
16718 }
16719
16720 if($Content=~/(\A|[^\@\w])\@\w/)
16721 {
16722 if(not $IncompleteRules{$Level}{$Kind})
16723 { # only one warning
16724 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16725 $IncompleteRules{$Level}{$Kind} = 1;
16726 }
16727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016728 return $Content;
16729}
16730
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016731sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016732{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016733 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016734 my $INTERFACE_PROBLEMS = "";
16735 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016736
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016737 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016738 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016739 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16740 if($SV and defined $CompatProblems{$Level}{$SN}) {
16741 next;
16742 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016743 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16744 my $DyLib = $Symbol_Library{1}{$Symbol};
16745 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16746 { # Symbol with Version
16747 $DyLib = $Symbol_Library{1}{$VSym};
16748 }
16749 if(not $DyLib)
16750 { # const global data
16751 $DyLib = "";
16752 }
16753 if($Level eq "Source" and $ReportFormat eq "html")
16754 { # do not show library name in HTML report
16755 $DyLib = "";
16756 }
16757
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016758 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016759 {
16760 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016762 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016763 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16764 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016766 if($Severity eq $TargetSeverity)
16767 {
16768 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16769 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016770 }
16771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016772 }
16773 }
16774 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016775
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016776 if($ReportFormat eq "xml")
16777 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016778 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016779 {
16780 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016781 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016782 {
16783 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016784 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16785 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016786 {
16787 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016788 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016789 {
16790 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16791 {
16792 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016793 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016794
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16796 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16797 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16798 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16799 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016800 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16801 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016803 $INTERFACE_PROBLEMS .= " </problem>\n";
16804 }
16805 }
16806 $INTERFACE_PROBLEMS .= " </symbol>\n";
16807 }
16808 $INTERFACE_PROBLEMS .= " </library>\n";
16809 }
16810 $INTERFACE_PROBLEMS .= " </header>\n";
16811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016812 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016813 }
16814 else
16815 { # HTML
16816 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016817 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016818 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016819 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016820 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016821 my (%NameSpaceSymbols, %NewSignature) = ();
16822 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016823 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016826 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016828 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 +040016829 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016831 my $Signature = get_Signature($Symbol, 1);
16832 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016833 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016834 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016835 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016837 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016838 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016839 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016841 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016842 }
16843 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16844 {
16845 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016846 $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 +040016847 $ProblemNum += 1;
16848 $ProblemsNum += 1;
16849 }
16850 }
16851 }
16852 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016853 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016854 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016855 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016857 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016858 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016859
16860 if($NameSpace)
16861 {
16862 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16863 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016865
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016866 $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 +040016867 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016868
16869 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016870 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016871 if($NameSpace) {
16872 $NSign = cut_Namespace($NSign, $NameSpace);
16873 }
16874 $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 +040016875 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016876
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016877 if($Symbol=~/\A(_Z|\?)/) {
16878 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16879 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016880
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016881 $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 +040016882 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016883 }
16884 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016885 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016886 }
16887 }
16888 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016889
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016890 if($INTERFACE_PROBLEMS)
16891 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016892 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16893 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16894 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016895 { # Safe Changes
16896 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016897 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016898 $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 +040016899 }
16900 }
16901 return $INTERFACE_PROBLEMS;
16902}
16903
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016904sub cut_Namespace($$)
16905{
16906 my ($N, $Ns) = @_;
16907 $N=~s/\b\Q$Ns\E:://g;
16908 return $N;
16909}
16910
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016911sub get_Report_TypeProblems($$)
16912{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016913 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016914 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016915
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016916 my %ReportMap = ();
16917 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016918
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016919 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016921 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
16922
16923 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016924 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016925 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016927 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016928 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016929
16930 if($Severity eq $TargetSeverity)
16931 {
16932 $ReportMap{$HeaderName}{$TypeName} = 1;
16933 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016938
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016939 if($ReportFormat eq "xml")
16940 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016941 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016942 {
16943 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016944 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016946 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016947 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016948 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016949 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016950 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016951 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016952 $Kinds_Locations{$Kind}{$Location} = 1;
16953
16954 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
16955 if($Kinds_Target{$Kind}{$Target}) {
16956 next;
16957 }
16958 $Kinds_Target{$Kind}{$Target} = 1;
16959
16960 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016961 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16962 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16963 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16964 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16965 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016966 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16967 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 $TYPE_PROBLEMS .= " </problem>\n";
16970 }
16971 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016972 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016973 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 $TYPE_PROBLEMS .= showVTables($TypeName);
16975 }
16976 $TYPE_PROBLEMS .= " </type>\n";
16977 }
16978 $TYPE_PROBLEMS .= " </header>\n";
16979 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 }
16982 else
16983 { # HTML
16984 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016985 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016986 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016987 my (%NameSpace_Type) = ();
16988 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016989 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016990 }
16991 foreach my $NameSpace (sort keys(%NameSpace_Type))
16992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016993 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016994 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 +040016995 foreach my $TypeName (@SortedTypes)
16996 {
16997 my $ProblemNum = 1;
16998 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016999 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017000
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017001 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017003 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017005 $Kinds_Locations{$Kind}{$Location} = 1;
17006
17007 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17008 if($Kinds_Target{$Kind}{$Target}) {
17009 next;
17010 }
17011 $Kinds_Target{$Kind}{$Target} = 1;
17012
17013 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017014 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17015 {
17016 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017017 $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 +040017018 $ProblemNum += 1;
17019 $ProblemsNum += 1;
17020 }
17021 }
17022 }
17023 $ProblemNum -= 1;
17024 if($TYPE_REPORT)
17025 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017026 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017027 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017028 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017029 $ShowVTables = showVTables($TypeName);
17030 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017031
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017032 my $ShowType = show_Type($TypeName, 1, 1);
17033
17034 if($NameSpace)
17035 {
17036 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17037 $ShowType = cut_Namespace($ShowType, $NameSpace);
17038 $Affected = cut_Namespace($Affected, $NameSpace);
17039 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17040 }
17041
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017042 $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 +040017043 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17044 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17045 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17046 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 }
17048 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017049 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017050 }
17051 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017053 if($TYPE_PROBLEMS)
17054 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017055 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17056 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017057 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017058 { # Safe Changes
17059 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017060 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017061 $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 +040017062 }
17063 }
17064 return $TYPE_PROBLEMS;
17065}
17066
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017067sub show_Type($$$)
17068{
17069 my ($Name, $Html, $LibVersion) = @_;
17070 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17071 $TType = lc($TType);
17072 if($TType=~/struct|union|enum/) {
17073 $Name=~s/\A\Q$TType\E //g;
17074 }
17075 if($Html) {
17076 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17077 }
17078 else {
17079 $Name = $TType." ".$Name;
17080 }
17081 return $Name;
17082}
17083
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017084sub get_Anchor($$$)
17085{
17086 my ($Kind, $Level, $Severity) = @_;
17087 if($JoinReport)
17088 {
17089 if($Severity eq "Safe") {
17090 return "Other_".$Level."_Changes_In_".$Kind."s";
17091 }
17092 else {
17093 return $Kind."_".$Level."_Problems_".$Severity;
17094 }
17095 }
17096 else
17097 {
17098 if($Severity eq "Safe") {
17099 return "Other_Changes_In_".$Kind."s";
17100 }
17101 else {
17102 return $Kind."_Problems_".$Severity;
17103 }
17104 }
17105}
17106
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107sub showVTables($)
17108{
17109 my $TypeName = $_[0];
17110 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017111 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017112 if(defined $Type1{"VTable"}
17113 and keys(%{$Type1{"VTable"}}))
17114 {
17115 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017116 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017117 if(defined $Type2{"VTable"}
17118 and keys(%{$Type2{"VTable"}}))
17119 {
17120 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17121 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017122 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017123 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017124 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17125 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 }
17127 my $VTABLES = "";
17128 if($ReportFormat eq "xml")
17129 { # XML
17130 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017131 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017132 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017133 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017134 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17135 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017136 $VTABLES .= " </entry>\n";
17137 }
17138 $VTABLES .= " </vtable>\n\n";
17139 }
17140 else
17141 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017142 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017143 $VTABLES .= "<tr><th>Offset</th>";
17144 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017145 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017146 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017147 {
17148 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017149
17150 my $E1 = $Entries{$Index}{"E1"};
17151 my $E2 = $Entries{$Index}{"E2"};
17152
17153 if($E1 ne $E2
17154 and $E1!~/ 0x/
17155 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017156 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017157 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017158 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017159 $Color1 = " class='failed'";
17160 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017161 }
17162 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017163 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017164 }
17165 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017166 $VTABLES .= "<tr><th>".$Index."</th>\n";
17167 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17168 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 }
17170 $VTABLES .= "</table><br/>\n";
17171 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017172 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017173 }
17174 return $VTABLES;
17175 }
17176 }
17177 return "";
17178}
17179
17180sub simpleVEntry($)
17181{
17182 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017183 if(not defined $VEntry
17184 or $VEntry eq "") {
17185 return "";
17186 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017187
17188 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017189 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17190 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17191 if($VEntry=~/\A_ZThn.+\Z/) {
17192 $VEntry = "non-virtual thunk";
17193 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017194 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017195 # support for old GCC versions
17196 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17197 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17198 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017199 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17200 return $VEntry;
17201}
17202
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017203sub adjustParamPos($$$)
17204{
17205 my ($Pos, $Symbol, $LibVersion) = @_;
17206 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17207 {
17208 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17209 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17210 {
17211 return $Pos-1;
17212 }
17213
17214 return $Pos;
17215 }
17216
17217 return undef;
17218}
17219
17220sub getParamPos($$$)
17221{
17222 my ($Name, $Symbol, $LibVersion) = @_;
17223
17224 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17225 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17226 {
17227 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17228 foreach (keys(%{$Info->{"Param"}}))
17229 {
17230 if($Info->{"Param"}{$_}{"name"} eq $Name)
17231 {
17232 return $_;
17233 }
17234 }
17235 }
17236
17237 return undef;
17238}
17239
17240sub getParamName($)
17241{
17242 my $Loc = $_[0];
17243 $Loc=~s/\->.*//g;
17244 return $Loc;
17245}
17246
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017247sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017248{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017249 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017250
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017251 my $LIMIT = 10;
17252 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017253 $LIMIT = $AffectLimit;
17254 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017255
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017256 my @Kinds = sort keys(%{$Kinds_Locations});
17257 my %KLocs = ();
17258 foreach my $Kind (@Kinds)
17259 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017260 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 +030017261 $KLocs{$Kind} = \@Locs;
17262 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017263
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017264 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017265 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017266 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017267 if(index($Symbol, "_Z")==0
17268 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017269 { # duplicated problems for C2 constructors, D2 and D0 destructors
17270 next;
17271 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017272
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017273 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017274 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017275 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017276 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017277 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017278 next;
17279 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017280
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017281 if(index($Symbol, "\@")!=-1
17282 or index($Symbol, "\$")!=-1)
17283 {
17284 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17285
17286 if($Level eq "Source")
17287 { # remove symbol version
17288 $Symbol = $SN;
17289 }
17290
17291 if($SV and defined $CompatProblems{$Level}{$SN}
17292 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17293 { # duplicated problems for versioned symbols
17294 next;
17295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017297
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017298 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017299 if($Type_Name ne $Target_TypeName) {
17300 next;
17301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017302
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017303 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017304 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017305 }
17306 }
17307 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017308
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017309 %KLocs = (); # clear
17310
17311 my %SymSel = ();
17312 my $Num = 0;
17313 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017314 {
17315 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17316 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017317 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017318 {
17319 $SymSel{$Symbol}{"Loc"} = $Loc;
17320 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017321 last LOOP;
17322 }
17323 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017324
17325 $Num += 1;
17326
17327 if($Num>=$LIMIT) {
17328 last;
17329 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017330 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017333
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017334 if($ReportFormat eq "xml")
17335 { # XML
17336 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017337
17338 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017339 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017340 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017341 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017342 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017343
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017344 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017345 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017346 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017347 $Target .= " param=\"$PName\"";
17348 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017349 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017350 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017351 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017352 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017353 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017354 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017355 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017356
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017357 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017358 $Target .= " field=\"$1\"";
17359 }
17360
17361 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017362 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017363 $Affected .= " </symbol>\n";
17364 }
17365 $Affected .= " </affected>\n";
17366 }
17367 else
17368 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017369 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017371 my $Kind = $SymSel{$Symbol}{"Kind"};
17372 my $Loc = $SymSel{$Symbol}{"Loc"};
17373
17374 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017375 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017376 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017377 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17378
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017379 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017380 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017381 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017382
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017383 if(keys(%SymLocKind)>$LIMIT) {
17384 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017385 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017386
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017387 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017388 if($Affected)
17389 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017390 my $Num = keys(%SymLocKind);
17391 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017392 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017393 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017394 }
17395 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017396
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017397 return $Affected;
17398}
17399
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017400sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017402 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017403 if($L2=~/\A(retval|this)\b/
17404 and $L1!~/\A(retval|this)\b/)
17405 {
17406 if($L1!~/\-\>/) {
17407 return 1;
17408 }
17409 elsif($L2=~/\-\>/) {
17410 return 1;
17411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 }
17413 return 0;
17414}
17415
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017416sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017417{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017418 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017419
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017420 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017421
17422 my $Location_I = $Location;
17423 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17424
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017425 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017426
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017427 if($Kind eq "Overridden_Virtual_Method"
17428 or $Kind eq "Overridden_Virtual_Method_B") {
17429 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17430 }
17431 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17432 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017433 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17436 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017437 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17438 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017440 if($ClassName eq $Problem{"Type_Name"}) {
17441 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17442 }
17443 else {
17444 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17445 }
17446 }
17447 else
17448 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017449 my $TypeID = undef;
17450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017451 if($Location=~/retval/)
17452 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017453 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017454 push(@Sentence, "Field \'".$Location."\' in return value");
17455 }
17456 else {
17457 push(@Sentence, "Return value");
17458 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017459
17460 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461 }
17462 elsif($Location=~/this/)
17463 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017464 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17466 }
17467 else {
17468 push(@Sentence, "\'this\' pointer");
17469 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017470
17471 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017472 }
17473 else
17474 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017475
17476 my $PName = getParamName($Location);
17477 my $PPos = getParamPos($PName, $Symbol, 1);
17478
17479 if(index($Location, "->")!=-1) {
17480 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017481 }
17482 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017483 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017484 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017485 if($PName) {
17486 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017487 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017488
17489 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17490 }
17491
17492 if($Location!~/this/)
17493 {
17494 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017495 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017496 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017497 push(@Sentence, "(pointer)");
17498 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017499 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017500 push(@Sentence, "(reference)");
17501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017502 }
17503 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017505 if($Location eq "this") {
17506 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17507 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017508 else
17509 {
17510 my $Location_T = $Location;
17511 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17512
17513 my $TypeID_Problem = $TypeID;
17514 if($Location_T) {
17515 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17516 }
17517
17518 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17519 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17520 }
17521 else {
17522 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17523 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017524 }
17525 }
17526 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017527 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017528 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 +040017529 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017530
17531 my $Sent = join(" ", @Sentence);
17532
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017533 $Sent=~s/->/./g;
17534
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017535 if($ReportFormat eq "xml")
17536 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017537 $Sent=~s/'//g;
17538 }
17539
17540 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017541}
17542
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017543sub getFieldType($$$)
17544{
17545 my ($Location, $TypeId, $LibVersion) = @_;
17546
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017547 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017548
17549 foreach my $Name (@Fields)
17550 {
17551 my %Info = get_BaseType($TypeId, $LibVersion);
17552
17553 foreach my $Pos (keys(%{$Info{"Memb"}}))
17554 {
17555 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17556 {
17557 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17558 last;
17559 }
17560 }
17561 }
17562
17563 return $TypeId;
17564}
17565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017566sub get_XmlSign($$)
17567{
17568 my ($Symbol, $LibVersion) = @_;
17569 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17570 my $Report = "";
17571 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17572 {
17573 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017574 my $Type = $Info->{"Param"}{$Pos}{"type"};
17575 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017576 foreach my $Typedef (keys(%ChangedTypedef))
17577 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017578 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17579 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017581 }
17582 $Report .= " <param pos=\"$Pos\">\n";
17583 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017584 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017585 $Report .= " </param>\n";
17586 }
17587 if(my $Return = $Info->{"Return"})
17588 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017589 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017590 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017591 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017592 $Report .= " </retval>\n";
17593 }
17594 return $Report;
17595}
17596
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017597sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017598{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017599 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017600 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017601 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017602 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017603 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17604 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017605 next;
17606 }
17607 $Report .= " <symbol name=\"$Symbol\">\n";
17608 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017609 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017610 {
17611 if(defined $CompleteSignature{1}{$Symbol}
17612 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17613 {
17614 $P1 = get_XmlSign($Symbol, 1);
17615 $S1 = get_Signature($Symbol, 1);
17616 }
17617 elsif($Symbol=~/\A(_Z|\?)/) {
17618 $S1 = $tr_name{$Symbol};
17619 }
17620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017621 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017622 {
17623 if(defined $CompleteSignature{2}{$Symbol}
17624 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17625 {
17626 $P2 = get_XmlSign($Symbol, 2);
17627 $S2 = get_Signature($Symbol, 2);
17628 }
17629 elsif($Symbol=~/\A(_Z|\?)/) {
17630 $S2 = $tr_name{$Symbol};
17631 }
17632 }
17633 if($S1)
17634 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017635 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017636 $Report .= $P1;
17637 $Report .= " </old>\n";
17638 }
17639 if($S2 and $S2 ne $S1)
17640 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017641 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017642 $Report .= $P2;
17643 $Report .= " </new>\n";
17644 }
17645 $Report .= " </symbol>\n";
17646 }
17647 $Report .= "</symbols_info>\n";
17648 return $Report;
17649}
17650
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017651sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017652{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017653 my ($Level, $Report) = @_;
17654 if($ReportFormat eq "xml") {
17655 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 }
17657 if($StdOut)
17658 { # --stdout option
17659 print STDOUT $Report;
17660 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017661 else
17662 {
17663 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017664 mkpath(get_dirname($RPath));
17665
17666 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17667 print REPORT $Report;
17668 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017669 }
17670}
17671
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017672sub getReport($)
17673{
17674 my $Level = $_[0];
17675 if($ReportFormat eq "xml")
17676 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017677 if($Level eq "Join")
17678 {
17679 my $Report = "<reports>\n";
17680 $Report .= getReport("Binary");
17681 $Report .= getReport("Source");
17682 $Report .= "</reports>\n";
17683 return $Report;
17684 }
17685 else
17686 {
17687 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17688 my ($Summary, $MetaData) = get_Summary($Level);
17689 $Report .= $Summary."\n";
17690 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17691 $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 +040017692
17693 # additional symbols info (if needed)
17694 # $Report .= get_Report_SymbolsInfo($Level);
17695
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017696 $Report .= "</report>\n";
17697 return $Report;
17698 }
17699 }
17700 else
17701 { # HTML
17702 my $CssStyles = readModule("Styles", "Report.css");
17703 my $JScripts = readModule("Scripts", "Sections.js");
17704 if($Level eq "Join")
17705 {
17706 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17707 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017708 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017709 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17710 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 +040017711 my ($BSummary, $BMetaData) = get_Summary("Binary");
17712 my ($SSummary, $SMetaData) = get_Summary("Source");
17713 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 +030017714 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017715 <br/>
17716 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017717 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17718 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017719 </div>";
17720 $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>";
17721 $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 +030017722 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017723 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017724 return $Report;
17725 }
17726 else
17727 {
17728 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017729 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17730 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17731 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 +040017732 if($Level eq "Binary")
17733 {
17734 if(getArch(1) eq getArch(2)
17735 and getArch(1) ne "unknown") {
17736 $Description .= " on ".showArch(getArch(1));
17737 }
17738 }
17739 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 +030017740 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017741 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17742 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17743 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017744 $Report .= "</div>\n<br/><br/><br/>\n";
17745 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017746 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017747 return $Report;
17748 }
17749 }
17750}
17751
17752sub createReport()
17753{
17754 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017755 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017756 writeReport("Join", getReport("Join"));
17757 }
17758 elsif($DoubleReport)
17759 { # default
17760 writeReport("Binary", getReport("Binary"));
17761 writeReport("Source", getReport("Source"));
17762 }
17763 elsif($BinaryOnly)
17764 { # --binary
17765 writeReport("Binary", getReport("Binary"));
17766 }
17767 elsif($SourceOnly)
17768 { # --source
17769 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017770 }
17771}
17772
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017773sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017774{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017775 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017776
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017777 $Footer .= "<hr/>\n";
17778 $Footer .= "<div class='footer' align='right'>";
17779 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17780 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017781 $Footer .= "<br/>\n";
17782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017783 return $Footer;
17784}
17785
17786sub get_Report_Problems($$)
17787{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017788 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017789
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017790 my $Report = get_Report_TypeProblems($Severity, $Level);
17791 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017792 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017793 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017794
17795 if($Severity eq "Low" or $Severity eq "Safe") {
17796 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017797 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017798
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017799 if($ReportFormat eq "html")
17800 {
17801 if($Report)
17802 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017803 if($JoinReport)
17804 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017805 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017806 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17807 }
17808 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017809 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017812 else
17813 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017814 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017815 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17816 }
17817 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017818 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017820 }
17821 }
17822 }
17823 return $Report;
17824}
17825
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017826sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017827{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017828 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017829
17830 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17831 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17832 $Head .= "<head>\n";
17833 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17834 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17835 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17836 $Head .= "<title>$Title</title>\n";
17837 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17838 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17839 $Head .= "</head>\n";
17840
17841 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017842}
17843
17844sub insertIDs($)
17845{
17846 my $Text = $_[0];
17847 while($Text=~/CONTENT_ID/)
17848 {
17849 if(int($Content_Counter)%2) {
17850 $ContentID -= 1;
17851 }
17852 $Text=~s/CONTENT_ID/c_$ContentID/;
17853 $ContentID += 1;
17854 $Content_Counter += 1;
17855 }
17856 return $Text;
17857}
17858
17859sub checkPreprocessedUnit($)
17860{
17861 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017862 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017863 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017864 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017865
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017866 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017867 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017868 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017869 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017870 chomp($Line);
17871 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017872 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017873 $CurHeader = path_format($1, $OSgroup);
17874 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017875 $CurClass = "";
17876
17877 if(index($CurHeader, $TMP_DIR)==0) {
17878 next;
17879 }
17880
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017881 if(substr($CurHeaderName, 0, 1) eq "<")
17882 { # <built-in>, <command-line>, etc.
17883 $CurHeaderName = "";
17884 $CurHeader = "";
17885 }
17886
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017887 if($ExtraInfo)
17888 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017889 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017890 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17891 }
17892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017893 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017894 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017895 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017896 if($CurHeaderName)
17897 {
17898 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17899 and not $Registered_Headers{$Version}{$CurHeader})
17900 { # not a target
17901 next;
17902 }
17903 if(not is_target_header($CurHeaderName, 1)
17904 and not is_target_header($CurHeaderName, 2))
17905 { # user-defined header
17906 next;
17907 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017908 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017909 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017910
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017911 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017912 {
17913 my ($Name, $Value) = ($1, $2);
17914 if(not $Constants{$Version}{$Name}{"Access"})
17915 {
17916 $Constants{$Version}{$Name}{"Access"} = "public";
17917 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017918 if($CurHeaderName) {
17919 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17920 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017921 }
17922 }
17923 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17924 $Constants{$Version}{$1}{"Access"} = "private";
17925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017926 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017927 else
17928 {
17929 if(defined $ExtraDump)
17930 {
17931 if($Line=~/(\w+)\s*\(/)
17932 { # functions
17933 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17934 }
17935 #elsif($Line=~/(\w+)\s*;/)
17936 #{ # data
17937 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17938 #}
17939 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17940 $CurClass = $2;
17941 }
17942 }
17943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017944 }
17945 close(PREPROC);
17946 foreach my $Constant (keys(%{$Constants{$Version}}))
17947 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017948 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17949 {
17950 delete($Constants{$Version}{$Constant});
17951 next;
17952 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017953 if(not $ExtraDump and ($Constant=~/_h\Z/i
17954 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017955 { # skip
17956 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017957 }
17958 else {
17959 delete($Constants{$Version}{$Constant}{"Access"});
17960 }
17961 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017962 if($Debug)
17963 {
17964 mkpath($DEBUG_PATH{$Version});
17965 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17966 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017967}
17968
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017969sub uncoverConstant($$)
17970{
17971 my ($LibVersion, $Constant) = @_;
17972 return "" if(not $LibVersion or not $Constant);
17973 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17974 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17975 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17976 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017977
17978 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017979 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017980 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17981 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017982 {
17983 push(@RecurConstant, $Constant);
17984 my $Uncovered = uncoverConstant($LibVersion, $Value);
17985 if($Uncovered ne "") {
17986 $Value = $Uncovered;
17987 }
17988 pop(@RecurConstant);
17989 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017990
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017991 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017992 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017993 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17994 }
17995 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17996}
17997
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017998sub simpleConstant($$)
17999{
18000 my ($LibVersion, $Value) = @_;
18001 if($Value=~/\W/)
18002 {
18003 my $Value_Copy = $Value;
18004 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18005 {
18006 my $Word = $1;
18007 if($Value!~/$Word\s*\(/)
18008 {
18009 my $Val = uncoverConstant($LibVersion, $Word);
18010 if($Val ne "")
18011 {
18012 $Value=~s/\b$Word\b/$Val/g;
18013 }
18014 }
18015 }
18016 }
18017 return $Value;
18018}
18019
18020sub computeValue($)
18021{
18022 my $Value = $_[0];
18023
18024 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18025 return $1;
18026 }
18027
18028 if($Value=~/\A[\d\-\+()]+\Z/) {
18029 return eval($Value);
18030 }
18031
18032 return $Value;
18033}
18034
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018035my %IgnoreConstant = map {$_=>1} (
18036 "VERSION",
18037 "VERSIONCODE",
18038 "VERNUM",
18039 "VERS_INFO",
18040 "PATCHLEVEL",
18041 "INSTALLPREFIX",
18042 "VBUILD",
18043 "VPATCH",
18044 "VMINOR",
18045 "BUILD_STRING",
18046 "BUILD_TIME",
18047 "PACKAGE_STRING",
18048 "PRODUCTION",
18049 "CONFIGURE_COMMAND",
18050 "INSTALLDIR",
18051 "BINDIR",
18052 "CONFIG_FILE_PATH",
18053 "DATADIR",
18054 "EXTENSION_DIR",
18055 "INCLUDE_PATH",
18056 "LIBDIR",
18057 "LOCALSTATEDIR",
18058 "SBINDIR",
18059 "SYSCONFDIR",
18060 "RELEASE",
18061 "SOURCE_ID",
18062 "SUBMINOR",
18063 "MINOR",
18064 "MINNOR",
18065 "MINORVERSION",
18066 "MAJOR",
18067 "MAJORVERSION",
18068 "MICRO",
18069 "MICROVERSION",
18070 "BINARY_AGE",
18071 "INTERFACE_AGE",
18072 "CORE_ABI",
18073 "PATCH",
18074 "COPYRIGHT",
18075 "TIMESTAMP",
18076 "REVISION",
18077 "PACKAGE_TAG",
18078 "PACKAGEDATE",
18079 "NUMVERSION",
18080 "Release",
18081 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018082);
18083
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018084sub constantFilter($$$)
18085{
18086 my ($Name, $Value, $Level) = @_;
18087
18088 if($Level eq "Binary")
18089 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018090 if($Name=~/_t\Z/)
18091 { # __malloc_ptr_t
18092 return 1;
18093 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018094 foreach (keys(%IgnoreConstant))
18095 {
18096 if($Name=~/(\A|_)$_(_|\Z)/)
18097 { # version
18098 return 1;
18099 }
18100 if(/\A[A-Z].*[a-z]\Z/)
18101 {
18102 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18103 { # version
18104 return 1;
18105 }
18106 }
18107 }
18108 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18109 { # version
18110 return 1;
18111 }
18112 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18113 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18114 return 1;
18115 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018116
18117 if($Value=~/\A["'].*['"]/i)
18118 { # string
18119 return 0;
18120 }
18121
18122 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18123 { # static int gcry_pth_init
18124 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018125 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018126 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018127 return 1;
18128 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018129 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018130 { # foo(p)
18131 return 1;
18132 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018133 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018134 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018135 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018136 return 1;
18137 }
18138 }
18139
18140 return 0;
18141}
18142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018143sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018144{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018145 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018146 foreach my $Constant (keys(%{$Constants{1}}))
18147 {
18148 if($SkipConstants{1}{$Constant})
18149 { # skipped by the user
18150 next;
18151 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018152
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018153 if(my $Header = $Constants{1}{$Constant}{"Header"})
18154 {
18155 if(not is_target_header($Header, 1)
18156 and not is_target_header($Header, 2))
18157 { # user-defined header
18158 next;
18159 }
18160 }
18161 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018162 next;
18163 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018164
18165 my $Old_Value = uncoverConstant(1, $Constant);
18166
18167 if(constantFilter($Constant, $Old_Value, $Level))
18168 { # separate binary and source problems
18169 next;
18170 }
18171
18172 if(not defined $Constants{2}{$Constant}{"Value"})
18173 { # removed
18174 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18175 "Target"=>$Constant,
18176 "Old_Value"=>$Old_Value );
18177 next;
18178 }
18179
18180 if($Constants{2}{$Constant}{"Value"} eq "")
18181 { # empty value
18182 # TODO: implement a rule
18183 next;
18184 }
18185
18186 my $New_Value = uncoverConstant(2, $Constant);
18187
18188 my $Old_Value_Pure = $Old_Value;
18189 my $New_Value_Pure = $New_Value;
18190
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018191 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18192 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18193 $New_Value_Pure=~s/(\W)\s+/$1/g;
18194 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018196 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018197
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018198 if($New_Value_Pure ne $Old_Value_Pure)
18199 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018200 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18201 { # complex values
18202 next;
18203 }
18204 if(computeValue($Old_Value) eq computeValue($New_Value))
18205 { # expressions
18206 next;
18207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018208 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18209 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18210 next;
18211 }
18212 if($Old_Value eq "0" and $New_Value eq "NULL")
18213 { # 0 => NULL
18214 next;
18215 }
18216 if($Old_Value eq "NULL" and $New_Value eq "0")
18217 { # NULL => 0
18218 next;
18219 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018220 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018221 "Target"=>$Constant,
18222 "Old_Value"=>$Old_Value,
18223 "New_Value"=>$New_Value );
18224 }
18225 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018226
18227 foreach my $Constant (keys(%{$Constants{2}}))
18228 {
18229 if(not defined $Constants{1}{$Constant}{"Value"})
18230 {
18231 if($SkipConstants{2}{$Constant})
18232 { # skipped by the user
18233 next;
18234 }
18235
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018236 if(my $Header = $Constants{2}{$Constant}{"Header"})
18237 {
18238 if(not is_target_header($Header, 1)
18239 and not is_target_header($Header, 2))
18240 { # user-defined header
18241 next;
18242 }
18243 }
18244 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018245 next;
18246 }
18247
18248 my $New_Value = uncoverConstant(2, $Constant);
18249 if(not defined $New_Value or $New_Value eq "") {
18250 next;
18251 }
18252
18253 if(constantFilter($Constant, $New_Value, $Level))
18254 { # separate binary and source problems
18255 next;
18256 }
18257
18258 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18259 "Target"=>$Constant,
18260 "New_Value"=>$New_Value );
18261 }
18262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018263}
18264
18265sub convert_integer($)
18266{
18267 my $Value = $_[0];
18268 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018269 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018270 return hex($Value);
18271 }
18272 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018273 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018274 return oct($Value);
18275 }
18276 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018277 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018278 return oct($Value);
18279 }
18280 else {
18281 return $Value;
18282 }
18283}
18284
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018285sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018286{
18287 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018288 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018289 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018290 {
18291 if($LibVersion==1)
18292 {
18293 printMsg("WARNING", "checking headers only");
18294 $CheckHeadersOnly = 1;
18295 }
18296 else {
18297 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18298 }
18299 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018300
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018301 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018302 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018303 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018304
18305 if($CheckUndefined)
18306 {
18307 my %UndefinedLibs = ();
18308
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018309 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18310
18311 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018312 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018313 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018314 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018315 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018316 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018317 if($Symbol_Library{$LibVersion}{$Symbol}
18318 or $DepSymbol_Library{$LibVersion}{$Symbol})
18319 { # exported by target library
18320 next;
18321 }
18322 if(index($Symbol, '@')!=-1)
18323 { # exported default symbol version (@@)
18324 $Symbol=~s/\@/\@\@/;
18325 if($Symbol_Library{$LibVersion}{$Symbol}
18326 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18327 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018328 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018329 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018330 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18331 $UndefinedLibs{$Path} = 1;
18332 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018333 }
18334 }
18335 }
18336 if($ExtraInfo)
18337 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018338 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018339 {
18340 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018341 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018342 foreach (@Paths)
18343 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018344 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018345 my ($Dir, $Name) = separate_path($_);
18346
18347 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018348 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018349 }
18350
18351 $Name = parse_libname($Name, "name", $OStarget);
18352 $Name=~s/\Alib//;
18353
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018354 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018355 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018356
18357 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18358 {
18359 $LibString = " -L".esc($Dir).$LibString;
18360 }
18361
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018362 writeFile($ExtraInfo."/libs-string", $LibString);
18363 }
18364 }
18365 }
18366
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018367 if($ExtraInfo) {
18368 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18369 }
18370
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018371 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018372 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018373 if($#LibPaths!=-1)
18374 {
18375 if(not keys(%{$Symbol_Library{$LibVersion}}))
18376 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018377 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018378 printMsg("WARNING", "checking headers only");
18379 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018380 }
18381 }
18382 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018383
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018384 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018385 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018386}
18387
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018388my %Prefix_Lib_Map=(
18389 # symbols for autodetecting library dependencies (by prefix)
18390 "pthread_" => ["libpthread"],
18391 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18392 "cairo_" => ["libcairo"],
18393 "gtk_" => ["libgtk-x11-2.0"],
18394 "atk_" => ["libatk-1.0"],
18395 "gdk_" => ["libgdk-x11-2.0"],
18396 "gl" => ["libGL"],
18397 "glu" => ["libGLU"],
18398 "popt" => ["libpopt"],
18399 "Py" => ["libpython"],
18400 "jpeg_" => ["libjpeg"],
18401 "BZ2_" => ["libbz2"],
18402 "Fc" => ["libfontconfig"],
18403 "Xft" => ["libXft"],
18404 "SSL_" => ["libssl"],
18405 "sem_" => ["libpthread"],
18406 "snd_" => ["libasound"],
18407 "art_" => ["libart_lgpl_2"],
18408 "dbus_g" => ["libdbus-glib-1"],
18409 "GOMP_" => ["libgomp"],
18410 "omp_" => ["libgomp"],
18411 "cms" => ["liblcms"]
18412);
18413
18414my %Pattern_Lib_Map=(
18415 "SL[a-z]" => ["libslang"]
18416);
18417
18418my %Symbol_Lib_Map=(
18419 # symbols for autodetecting library dependencies (by name)
18420 "pow" => "libm",
18421 "fmod" => "libm",
18422 "sin" => "libm",
18423 "floor" => "libm",
18424 "cos" => "libm",
18425 "dlopen" => "libdl",
18426 "deflate" => "libz",
18427 "inflate" => "libz",
18428 "move_panel" => "libpanel",
18429 "XOpenDisplay" => "libX11",
18430 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018431 "clock_gettime" => "librt",
18432 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018433);
18434
18435sub find_SymbolLibs($$)
18436{
18437 my ($LibVersion, $Symbol) = @_;
18438
18439 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18440 { # debug symbols
18441 return ();
18442 }
18443
18444 my %Paths = ();
18445
18446 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18447 {
18448 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18449 $Paths{$Path} = 1;
18450 }
18451 }
18452
18453 if(my $SymbolPrefix = getPrefix($Symbol))
18454 {
18455 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18456 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18457 }
18458
18459 if(not keys(%Paths))
18460 {
18461 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18462 {
18463 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18464 {
18465 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18466 $Paths{$Path} = 1;
18467 }
18468 }
18469 }
18470 }
18471
18472 if(not keys(%Paths))
18473 {
18474 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18475 {
18476 if($Symbol=~/\A$Prefix/)
18477 {
18478 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18479 {
18480 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18481 $Paths{$Path} = 1;
18482 }
18483 }
18484 }
18485 }
18486 }
18487
18488 if(not keys(%Paths))
18489 {
18490 if($SymbolPrefix)
18491 { # try to find a library by symbol prefix
18492 if($SymbolPrefix eq "inotify" and
18493 index($Symbol, "\@GLIBC")!=-1)
18494 {
18495 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18496 $Paths{$Path} = 1;
18497 }
18498 }
18499 else
18500 {
18501 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18502 $Paths{$Path} = 1;
18503 }
18504 }
18505 }
18506 }
18507
18508 if(my @Paths = keys(%Paths)) {
18509 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18510 }
18511 }
18512 return keys(%Paths);
18513}
18514
18515sub get_LibPath_Prefix($$)
18516{
18517 my ($LibVersion, $Prefix) = @_;
18518
18519 $Prefix = lc($Prefix);
18520 $Prefix=~s/[_]+\Z//g;
18521
18522 foreach ("-2", "2", "-1", "1", "")
18523 { # libgnome-2.so
18524 # libxml2.so
18525 # libdbus-1.so
18526 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18527 return $Path;
18528 }
18529 }
18530 return "";
18531}
18532
18533sub getPrefix($)
18534{
18535 my $Str = $_[0];
18536 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18537 { # XmuValidArea: Xmu
18538 return $1;
18539 }
18540 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18541 { # snfReadFont: snf
18542 return $1;
18543 }
18544 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18545 { # XRRTimes: XRR
18546 return $1;
18547 }
18548 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18549 { # H5HF_delete: H5
18550 return $1;
18551 }
18552 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18553 { # alarm_event_add: alarm_
18554 return $1;
18555 }
18556 elsif($Str=~/\A(([a-z])\2{1,})/i)
18557 { # ffopen
18558 return $1;
18559 }
18560 return "";
18561}
18562
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018563sub getSymbolSize($$)
18564{ # size from the shared library
18565 my ($Symbol, $LibVersion) = @_;
18566 return 0 if(not $Symbol);
18567 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18568 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18569 {
18570 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18571 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18572 {
18573 if($Size<0) {
18574 return -$Size;
18575 }
18576 }
18577 }
18578 return 0;
18579}
18580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018581sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018582{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18583 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018584 my ($Name, $Type) = @_;
18585
18586 # single
18587 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018588 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018589 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018590 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018591 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018592
18593 # double
18594 if($Name=~/$DEFAULT_STD_PARMS/)
18595 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018596 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018597 {
18598 my ($ShortName, $FuncParams) = split_Signature($Name);
18599
18600 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18601 {
18602 if(index($FParam, "<")!=-1)
18603 {
18604 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18605 my $FParam_N = canonifyName($FParam, "T");
18606 if($FParam_N ne $FParam) {
18607 $Name=~s/\Q$FParam\E/$FParam_N/g;
18608 }
18609 }
18610 }
18611 }
18612 elsif($Type eq "T")
18613 {
18614 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18615
18616 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018617 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018618 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018619 my $FParam = $TParams[0];
18620 foreach my $Pos (1 .. $#TParams)
18621 {
18622 my $TParam = $TParams[$Pos];
18623 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18624 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18625 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018626 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018627 }
18628 }
18629 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018630 if($Type eq "S") {
18631 return formatName($Name, "S");
18632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018633 return $Name;
18634}
18635
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018636sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018637{
18638 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018639 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018640 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018641 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018642 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018643 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018644 next if($tr_name{$Symbol});
18645 $Symbol=~s/[\@\$]+(.*)\Z//;
18646 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018647 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018648 elsif(index($Symbol, "?")==0)
18649 {
18650 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018651 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018652 }
18653 else
18654 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018655 $tr_name{$Symbol} = $Symbol;
18656 $mangled_name_gcc{$Symbol} = $Symbol;
18657 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018658 }
18659 }
18660 if($#MnglNames1 > -1)
18661 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018662 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018663 foreach my $MnglName (@MnglNames1)
18664 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018665 if(my $Unmangled = pop(@UnmangledNames))
18666 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018667 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018668 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18669 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18670 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018671 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018672 and $tr_name{$MnglName}=~/vtable for (.+)/)
18673 { # bind class name and v-table symbol
18674 my $ClassName = $1;
18675 $ClassVTable{$ClassName} = $MnglName;
18676 $VTableClass{$MnglName} = $ClassName;
18677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018678 }
18679 }
18680 }
18681 if($#MnglNames2 > -1)
18682 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018683 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018684 foreach my $MnglName (@MnglNames2)
18685 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018686 if(my $Unmangled = pop(@UnmangledNames))
18687 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018688 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018689 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018691 }
18692 }
18693 return \%tr_name;
18694}
18695
18696sub link_symbol($$$)
18697{
18698 my ($Symbol, $RunWith, $Deps) = @_;
18699 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18700 return 1;
18701 }
18702 if($Deps eq "+Deps")
18703 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018704 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018705 return 1;
18706 }
18707 }
18708 return 0;
18709}
18710
18711sub link_symbol_internal($$$)
18712{
18713 my ($Symbol, $RunWith, $Where) = @_;
18714 return 0 if(not $Where or not $Symbol);
18715 if($Where->{$RunWith}{$Symbol})
18716 { # the exact match by symbol name
18717 return 1;
18718 }
18719 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18720 { # indirect symbol version, i.e.
18721 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018722 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018723 if($Where->{$RunWith}{$VSym}) {
18724 return 1;
18725 }
18726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018727 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018728 if($Sym and $Ver)
18729 { # search for the symbol with the same version
18730 # or without version
18731 if($Where->{$RunWith}{$Sym})
18732 { # old: foo@v|foo@@v
18733 # new: foo
18734 return 1;
18735 }
18736 if($Where->{$RunWith}{$Sym."\@".$Ver})
18737 { # old: foo|foo@@v
18738 # new: foo@v
18739 return 1;
18740 }
18741 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18742 { # old: foo|foo@v
18743 # new: foo@@v
18744 return 1;
18745 }
18746 }
18747 return 0;
18748}
18749
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018750sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018751{
18752 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018753 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018754 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018755 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018756 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018757 my $NM = get_CmdPath("nm");
18758 if(not $NM) {
18759 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018760 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018761 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018762 while(<APP>)
18763 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018764 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018765 push(@Imported, $1);
18766 }
18767 }
18768 close(APP);
18769 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018770 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018771 {
18772 my $DumpBinCmd = get_CmdPath("dumpbin");
18773 if(not $DumpBinCmd) {
18774 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18775 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018776 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018777 while(<APP>)
18778 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018779 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18780 push(@Imported, $1);
18781 }
18782 }
18783 close(APP);
18784 }
18785 else
18786 {
18787 my $ReadelfCmd = get_CmdPath("readelf");
18788 if(not $ReadelfCmd) {
18789 exitStatus("Not_Found", "can't find \"readelf\"");
18790 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018791 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018792 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793 while(<APP>)
18794 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018795 if(defined $symtab)
18796 { # do nothing with symtab
18797 if(index($_, "'.dynsym'")!=-1)
18798 { # dynamic table
18799 $symtab = undef;
18800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018801 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018802 elsif(index($_, "'.symtab'")!=-1)
18803 { # symbol table
18804 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018805 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018806 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018807 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018808 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18809 if($Ndx eq "UND")
18810 { # only imported symbols
18811 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018812 }
18813 }
18814 }
18815 close(APP);
18816 }
18817 return @Imported;
18818}
18819
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018820my %ELF_BIND = map {$_=>1} (
18821 "WEAK",
18822 "GLOBAL"
18823);
18824
18825my %ELF_TYPE = map {$_=>1} (
18826 "FUNC",
18827 "IFUNC",
18828 "OBJECT",
18829 "COMMON"
18830);
18831
18832my %ELF_VIS = map {$_=>1} (
18833 "DEFAULT",
18834 "PROTECTED"
18835);
18836
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018837sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018838{ # read the line of 'readelf' output corresponding to the symbol
18839 my @Info = split(/\s+/, $_[0]);
18840 # Num: Value Size Type Bind Vis Ndx Name
18841 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018842 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018843 shift(@Info); # spaces
18844 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018845
18846 if($#Info==7)
18847 { # UND SYMBOL (N)
18848 if($Info[7]=~/\(\d+\)/) {
18849 pop(@Info);
18850 }
18851 }
18852
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018853 if($#Info!=6)
18854 { # other lines
18855 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018856 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018857 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018858 return () if(not defined $ELF_BIND{$Info[3]});
18859 return () if(not defined $ELF_VIS{$Info[4]});
18860 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18861 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18862 return ();
18863 }
18864 if($OStarget eq "symbian")
18865 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18866 if(index($Info[6], "_._.absent_export_")!=-1)
18867 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18868 return ();
18869 }
18870 $Info[6]=~s/\@.+//g; # remove version
18871 }
18872 if(index($Info[2], "0x") == 0)
18873 { # size == 0x3d158
18874 $Info[2] = hex($Info[2]);
18875 }
18876 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018877}
18878
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018879sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018880{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018881 my ($LibVersion, $Name) = @_;
18882 return "" if(not $LibVersion or not $Name);
18883 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18884 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018885 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018886 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18887}
18888
18889sub get_LibPath_I($$)
18890{
18891 my ($LibVersion, $Name) = @_;
18892 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018893 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018894 if(-f $Name)
18895 { # absolute path
18896 return $Name;
18897 }
18898 else
18899 { # broken
18900 return "";
18901 }
18902 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018903 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018904 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018905 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018906 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018907 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018908 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018909 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018910 }
18911 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18912 { # ldconfig default paths
18913 return $DefaultPath;
18914 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018915 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018916 { # search in default linker directories
18917 # and then in all system paths
18918 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018919 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018920 }
18921 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018922 if(not defined $Cache{"checkSystemFiles"}) {
18923 checkSystemFiles();
18924 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018925 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18926 return $AllObjects[0];
18927 }
18928 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18929 {
18930 if($ShortName ne $Name)
18931 { # FIXME: check this case
18932 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18933 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018934 }
18935 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018936 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018937 # can't find
18938 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018939}
18940
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018941sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018942{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18944 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018945
18946 my $Real_Path = realpath($Lib_Path);
18947
18948 if(not $Real_Path)
18949 { # broken link
18950 return ();
18951 }
18952
18953 my $Lib_Name = get_filename($Real_Path);
18954
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018955 if($ExtraInfo)
18956 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018957 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018958 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018959 }
18960
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018961 if($IsNeededLib)
18962 {
18963 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18964 return ();
18965 }
18966 }
18967 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018969
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018970 push(@RecurLib, $Lib_Name);
18971 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018972 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18973
18974 if(not $IsNeededLib)
18975 { # special cases: libstdc++ and libc
18976 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18977 {
18978 if($ShortName eq "libstdc++")
18979 { # libstdc++.so.6
18980 $STDCXX_TESTING = 1;
18981 }
18982 elsif($ShortName eq "libc")
18983 { # libc-2.11.3.so
18984 $GLIBC_TESTING = 1;
18985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018986 }
18987 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018988 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018989 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018990 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018991 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018992 mkpath(get_dirname($DebugPath));
18993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018994 if($OStarget eq "macos")
18995 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018996 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018997 if(not $NM) {
18998 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018999 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019000 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019001 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019002 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019003 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019004 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019005 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019006 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019007 else
19008 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019009 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019011 while(<LIB>)
19012 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019013 if($CheckUndefined)
19014 {
19015 if(not $IsNeededLib)
19016 {
19017 if(/ U _([\w\$]+)\s*\Z/)
19018 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019019 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019020 next;
19021 }
19022 }
19023 }
19024
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019025 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019026 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019027 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019028 if($IsNeededLib)
19029 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019030 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019031 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019032 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19033 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019035 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019036 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019037 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019038 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19039 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019040 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19041 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019042 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019043 setLanguage($LibVersion, "C++");
19044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019046 }
19047 }
19048 }
19049 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019050
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019051 if($Deps)
19052 {
19053 if($LIB_TYPE eq "dynamic")
19054 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019055
19056 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019057 if(not $OtoolCmd) {
19058 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019059 }
19060
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019061 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19062 while(<LIB>)
19063 {
19064 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19065 and $1 ne $Lib_Path) {
19066 $NeededLib{$1} = 1;
19067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019068 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019069 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019070 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019071 }
19072 }
19073 elsif($OStarget eq "windows")
19074 { # Windows *.dll, *.lib
19075 my $DumpBinCmd = get_CmdPath("dumpbin");
19076 if(not $DumpBinCmd) {
19077 exitStatus("Not_Found", "can't find \"dumpbin\"");
19078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019079 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019080 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019081 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019082 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019083 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019084 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019085 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019086 else
19087 { # write to pipe
19088 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019090 while(<LIB>)
19091 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19092 # 1198 4AD SetThreadToken (forwarded to ...)
19093 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019094 # 1 0 00005B30 ??0?N = ... (with pdb)
19095 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019096 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019097 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019098 { # dynamic, static and forwarded symbols
19099 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019100 if($IsNeededLib)
19101 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019102 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019103 {
19104 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19105 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019107 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019108 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 {
19110 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19111 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019112 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19113 {
19114 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19115 setLanguage($LibVersion, "C++");
19116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019118 }
19119 }
19120 }
19121 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019122
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019123 if($Deps)
19124 {
19125 if($LIB_TYPE eq "dynamic")
19126 { # dependencies
19127 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19128 while(<LIB>)
19129 {
19130 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19131 and $1 ne $Lib_Path) {
19132 $NeededLib{path_format($1, $OSgroup)} = 1;
19133 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019135 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 }
19138 }
19139 else
19140 { # Unix; *.so, *.a
19141 # Symbian: *.dso, *.lib
19142 my $ReadelfCmd = get_CmdPath("readelf");
19143 if(not $ReadelfCmd) {
19144 exitStatus("Not_Found", "can't find \"readelf\"");
19145 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019146 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019147 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019148 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019149 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019150 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019151 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019152 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019153 else
19154 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019155 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019156 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019157 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019158 while(<LIB>)
19159 {
19160 if($LIB_TYPE eq "dynamic")
19161 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019162 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019163 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019164 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019165 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019166 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019167 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019168 # do nothing with symtab
19169 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019170 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019171 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019172 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019173 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019174 next;
19175 }
19176 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019177 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019179 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019180 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019181 if($CheckUndefined)
19182 {
19183 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019184 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019185 }
19186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019187 next;
19188 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019189 if($Bind eq "WEAK")
19190 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019191 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019192 if($Weak eq "-Weak")
19193 { # skip WEAK symbols
19194 next;
19195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019196 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019197 my $Short = $Symbol;
19198 $Short=~s/\@.+//g;
19199 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019200 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019201 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19202 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019203 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019204 if($IsNeededLib)
19205 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019206 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019207 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019208 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19209 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019212 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019213 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019214 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19215 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19216 if($Vers)
19217 {
19218 if($LIB_EXT eq "so")
19219 { # value
19220 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19221 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019223 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019224 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19225 {
19226 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19227 setLanguage($LibVersion, "C++");
19228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019230 }
19231 }
19232 }
19233 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019234
19235 if($Deps and $LIB_TYPE eq "dynamic")
19236 { # dynamic library specifics
19237 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19238 open(LIB, $Cmd." |");
19239
19240 while(<LIB>)
19241 {
19242 if(/NEEDED.+\[([^\[\]]+)\]/)
19243 { # dependencies:
19244 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19245 $NeededLib{$1} = 1;
19246 }
19247 }
19248
19249 close(LIB);
19250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019252 if($Vers)
19253 {
19254 if(not $IsNeededLib and $LIB_EXT eq "so")
19255 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019256 my %Found = ();
19257
19258 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019259 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019261 next if(index($Symbol,"\@")==-1);
19262 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019263 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019264 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019265 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019266 if($Symbol_SameValue ne $Symbol
19267 and index($Symbol_SameValue,"\@")==-1)
19268 {
19269 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019270 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019271 last;
19272 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019273 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019274 }
19275 }
19276
19277 # default
19278 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19279 {
19280 next if(defined $Found{$Symbol});
19281 next if(index($Symbol,"\@\@")==-1);
19282
19283 if($Symbol=~/\A([^\@]*)\@\@/
19284 and not $SymVer{$LibVersion}{$1})
19285 {
19286 $SymVer{$LibVersion}{$1} = $Symbol;
19287 $Found{$Symbol} = 1;
19288 }
19289 }
19290
19291 # non-default
19292 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19293 {
19294 next if(defined $Found{$Symbol});
19295 next if(index($Symbol,"\@")==-1);
19296
19297 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19298 and not $SymVer{$LibVersion}{$1})
19299 {
19300 $SymVer{$LibVersion}{$1} = $Symbol;
19301 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019302 }
19303 }
19304 }
19305 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019306 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019307 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019308 foreach my $DyLib (sort keys(%NeededLib))
19309 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019310 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19311
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019312 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19313 {
19314 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19315 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19316 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019318 }
19319 }
19320 pop(@RecurLib);
19321 return $Library_Symbol{$LibVersion};
19322}
19323
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019324sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019325{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019326 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019327 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019328 return keys(%Prefixes);
19329}
19330
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019331sub get_prefixes_I($$)
19332{
19333 foreach my $P (@{$_[0]})
19334 {
19335 my @Parts = reverse(split(/[\/\\]+/, $P));
19336 my $Name = $Parts[0];
19337 foreach (1 .. $#Parts)
19338 {
19339 $_[1]->{$Name}{$P} = 1;
19340 last if($_>4 or $Parts[$_] eq "include");
19341 $Name = $Parts[$_].$SLASH.$Name;
19342 }
19343 }
19344}
19345
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019346sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019347{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019348 $Cache{"checkSystemFiles"} = 1;
19349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019350 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019351
19352 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019353 {
19354 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019355
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019356 my @Files = cmd_find($DevelPath,"f");
19357 foreach my $Link (cmd_find($DevelPath,"l"))
19358 { # add symbolic links
19359 if(-f $Link) {
19360 push(@Files, $Link);
19361 }
19362 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019363
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019364 # search for headers in /usr/lib
19365 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19366 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19367 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019368
19369 # search for libraries in /usr/lib (including symbolic links)
19370 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19371 foreach my $Path (@Libs)
19372 {
19373 my $N = get_filename($Path);
19374 $SystemObjects{$N}{$Path} = 1;
19375 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019376 }
19377 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019378
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019379 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019380 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019381 next if(not -d $DevelPath);
19382 # search for all header files in the /usr/include
19383 # with or without extension (ncurses.h, QtCore, ...)
19384 push(@SysHeaders, cmd_find($DevelPath,"f"));
19385 foreach my $Link (cmd_find($DevelPath,"l"))
19386 { # add symbolic links
19387 if(-f $Link) {
19388 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 }
19391 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019392 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019393}
19394
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019395sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019396{
19397 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019398 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019399 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19400 {
19401 if(not -e $Dest) {
19402 exitStatus("Access_Error", "can't access \'$Dest\'");
19403 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019404 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019405 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19406 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019407 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019408 }
19409 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019410 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019411}
19412
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019413sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019414{
19415 my ($Path, $LibVersion) = @_;
19416 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019417 my $Name = get_filename($Path);
19418 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019419 return 1;
19420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019421 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019422 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19423 return 1;
19424 }
19425 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19426 {
19427 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19428 return 1;
19429 }
19430 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019431 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019433 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019434 return 1;
19435 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019436 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019437 return 1;
19438 }
19439 }
19440 return 0;
19441}
19442
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019443sub specificHeader($$)
19444{
19445 my ($Header, $Spec) = @_;
19446 my $Name = get_filename($Header);
19447
19448 if($Spec eq "windows")
19449 {# MS Windows
19450 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19451 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19452 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19453 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19454 my @Dirs = (
19455 "win32",
19456 "win64",
19457 "win",
19458 "windows",
19459 "msvcrt"
19460 ); # /gsf-win32/
19461 if(my $DIRs = join("|", @Dirs)) {
19462 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19463 }
19464 }
19465 elsif($Spec eq "macos")
19466 { # Mac OS
19467 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19468 }
19469
19470 return 0;
19471}
19472
19473sub skipAlienHeader($)
19474{
19475 my $Path = $_[0];
19476 my $Name = get_filename($Path);
19477 my $Dir = get_dirname($Path);
19478
19479 if($Tolerance=~/2/)
19480 { # 2 - skip internal headers
19481 my @Terms = (
19482 "p",
19483 "priv",
19484 "int",
19485 "impl",
19486 "implementation",
19487 "internal",
19488 "private",
19489 "old",
19490 "compat",
19491 "debug",
19492 "test",
19493 "gen"
19494 );
19495
19496 my @Dirs = (
19497 "private",
19498 "priv",
19499 "port",
19500 "impl",
19501 "internal",
19502 "detail",
19503 "details",
19504 "old",
19505 "compat",
19506 "debug",
19507 "config",
19508 "compiler",
19509 "platform",
19510 "test"
19511 );
19512
19513 if(my $TERMs = join("|", @Terms)) {
19514 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19515 }
19516 if(my $DIRs = join("|", @Dirs)) {
19517 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19518 }
19519
19520 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19521 }
19522
19523 if($Tolerance=~/1/)
19524 { # 1 - skip non-Linux headers
19525 if($OSgroup ne "windows")
19526 {
19527 if(specificHeader($Path, "windows")) {
19528 return 1;
19529 }
19530 }
19531 if($OSgroup ne "macos")
19532 {
19533 if(specificHeader($Path, "macos")) {
19534 return 1;
19535 }
19536 }
19537 }
19538
19539 # valid
19540 return 0;
19541}
19542
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019543sub skipHeader($$)
19544{
19545 my ($Path, $LibVersion) = @_;
19546 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019547 if(defined $Cache{"skipHeader"}{$Path}) {
19548 return $Cache{"skipHeader"}{$Path};
19549 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019550 if(defined $Tolerance and $Tolerance=~/1|2/)
19551 { # --tolerant
19552 if(skipAlienHeader($Path)) {
19553 return ($Cache{"skipHeader"}{$Path} = 1);
19554 }
19555 }
19556 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19557 return 0;
19558 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019559 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19560}
19561
19562sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019563{ # returns:
19564 # 1 - if header should NOT be included and checked
19565 # 2 - if header should NOT be included, but should be checked
19566 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019567 my $Name = get_filename($Path);
19568 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019569 return $Kind;
19570 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019571 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19572 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019573 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019574 if(index($Path, $D)!=-1)
19575 {
19576 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19577 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019579 }
19580 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019581 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19582 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019583 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019584 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19585 {
19586 if($Name=~/$P/) {
19587 return $Kind;
19588 }
19589 if($P=~/[\/\\]/ and $Path=~/$P/) {
19590 return $Kind;
19591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019592 }
19593 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019595 return 0;
19596}
19597
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019598sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019599{
19600 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019601 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602 { # system directory
19603 return;
19604 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019605 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606 { # already registered
19607 return;
19608 }
19609 foreach my $Path (find_libs($Dir,"",1))
19610 {
19611 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019612 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019613 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019614 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019615 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19616}
19617
19618sub registerObject($$)
19619{
19620 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019621
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019622 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019623 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019624 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019625 {
19626 if(my $SONAME = getSONAME($Path)) {
19627 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19628 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019629 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019630 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19631 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019632 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019633
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019634 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019635 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019636 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019637 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019638 if($ObjArch ne getArch_GCC($LibVersion))
19639 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19640 $CheckedArch{$LibVersion} = 1;
19641 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 +040019642 }
19643 }
19644 }
19645}
19646
19647sub getArch_Object($)
19648{
19649 my $Path = $_[0];
19650
19651 my %MachineType = (
19652 "14C" => "x86",
19653 "8664" => "x86_64",
19654 "1C0" => "arm",
19655 "200" => "ia64"
19656 );
19657
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019658 my %ArchName = (
19659 "s390:31-bit" => "s390",
19660 "s390:64-bit" => "s390x",
19661 "powerpc:common" => "ppc32",
19662 "powerpc:common64" => "ppc64",
19663 "i386:x86-64" => "x86_64",
19664 "mips:3000" => "mips",
19665 "sparc:v8plus" => "sparcv9"
19666 );
19667
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019668 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019669 {
19670 my $DumpbinCmd = get_CmdPath("dumpbin");
19671 if(not $DumpbinCmd) {
19672 exitStatus("Not_Found", "can't find \"dumpbin\"");
19673 }
19674
19675 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19676 my $Out = `$Cmd`;
19677
19678 if($Out=~/(\w+)\smachine/)
19679 {
19680 if(my $Type = $MachineType{uc($1)})
19681 {
19682 return $Type;
19683 }
19684 }
19685 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019686 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019687 {
19688 my $ObjdumpCmd = get_CmdPath("objdump");
19689 if(not $ObjdumpCmd) {
19690 exitStatus("Not_Found", "can't find \"objdump\"");
19691 }
19692
19693 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019694
19695 if($OSgroup eq "windows") {
19696 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19697 }
19698 else {
19699 $Cmd = "LANG=$LOCALE ".$Cmd;
19700 }
19701 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019702
19703 if($Out=~/architecture:\s+([\w\-\:]+)/)
19704 {
19705 my $Arch = $1;
19706 if($Arch=~s/\:(.+)//)
19707 {
19708 my $Suffix = $1;
19709
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019710 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019711 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019712 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019713 }
19714 }
19715
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019716 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019717 $Arch = "x86";
19718 }
19719
19720 if($Arch eq "x86-64") {
19721 $Arch = "x86_64";
19722 }
19723
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019724 if($Arch eq "ia64-elf64") {
19725 $Arch = "ia64";
19726 }
19727
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019728 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019729 }
19730 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019731 elsif($OStarget=~/macos/)
19732 {
19733 my $OtoolCmd = get_CmdPath("otool");
19734 if(not $OtoolCmd) {
19735 exitStatus("Not_Found", "can't find \"otool\"");
19736 }
19737
19738 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19739 my $Out = qx/$Cmd/;
19740
19741 if($Out=~/X86_64/i) {
19742 return "x86_64";
19743 }
19744 elsif($Out=~/X86/i) {
19745 return "x86";
19746 }
19747 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019748 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019749 {
19750 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019751 # TODO
19752 }
19753
19754 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019755}
19756
19757sub getSONAME($)
19758{
19759 my $Path = $_[0];
19760 return if(not $Path);
19761 if(defined $Cache{"getSONAME"}{$Path}) {
19762 return $Cache{"getSONAME"}{$Path};
19763 }
19764 my $ObjdumpCmd = get_CmdPath("objdump");
19765 if(not $ObjdumpCmd) {
19766 exitStatus("Not_Found", "can't find \"objdump\"");
19767 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019768 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019769 if($OSgroup eq "windows") {
19770 $SonameCmd .= " | find \"SONAME\"";
19771 }
19772 else {
19773 $SonameCmd .= " | grep SONAME";
19774 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019775 if(my $SonameInfo = `$SonameCmd`)
19776 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019777 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19778 return ($Cache{"getSONAME"}{$Path} = $1);
19779 }
19780 }
19781 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782}
19783
19784sub getSOPaths_Dest($$)
19785{
19786 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019787 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019788 return ();
19789 }
19790 if(-f $Dest)
19791 {
19792 if(not parse_libname($Dest, "name", $OStarget)) {
19793 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019795 registerObject($Dest, $LibVersion);
19796 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019797 return ($Dest);
19798 }
19799 elsif(-d $Dest)
19800 {
19801 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019802 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019803 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19805 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019806 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019807 { # all files and symlinks that match the name of a library
19808 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19809 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019810 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019811 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019812 }
19813 }
19814 }
19815 else
19816 { # search for all files and symlinks
19817 foreach my $Path (find_libs($Dest,"",""))
19818 {
19819 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019820 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019821 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019822 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019823 }
19824 if($OSgroup eq "macos")
19825 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019826 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019827 {
19828 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019829 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019830 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019831 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19832 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019833 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019834 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019835 }
19836 }
19837 }
19838 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019839 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019840 }
19841 else {
19842 return ();
19843 }
19844}
19845
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019846sub isCyclical($$)
19847{
19848 my ($Stack, $Value) = @_;
19849 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019850}
19851
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019852sub getGCC_Opts($)
19853{ # to use in module
19854 my $LibVersion = $_[0];
19855
19856 my @Opts = ();
19857
19858 if($CompilerOptions{$LibVersion})
19859 { # user-defined options
19860 push(@Opts, $CompilerOptions{$LibVersion});
19861 }
19862 if($GccOptions)
19863 { # additional
19864 push(@Opts, $GccOptions);
19865 }
19866
19867 if(@Opts) {
19868 return join(" ", @Opts);
19869 }
19870
19871 return undef;
19872}
19873
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019874sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019875{
19876 my $LibVersion = $_[0];
19877
19878 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19879 return $Cache{"getArch_GCC"}{$LibVersion};
19880 }
19881
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019882 if(not $GCC_PATH) {
19883 return undef;
19884 }
19885
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019886 my $Arch = undef;
19887
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019888 if(my $Target = get_dumpmachine($GCC_PATH))
19889 {
19890 if($Target=~/x86_64/) {
19891 $Arch = "x86_64";
19892 }
19893 elsif($Target=~/i[3-6]86/) {
19894 $Arch = "x86";
19895 }
19896 elsif($Target=~/\Aarm/i) {
19897 $Arch = "arm";
19898 }
19899 }
19900
19901 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019902 {
19903 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19904
19905 my $Cmd = $GCC_PATH." test.c -o test";
19906 if(my $Opts = getGCC_Opts($LibVersion))
19907 { # user-defined options
19908 $Cmd .= " ".$Opts;
19909 }
19910
19911 chdir($TMP_DIR);
19912 system($Cmd);
19913 chdir($ORIG_DIR);
19914
19915 $Arch = getArch_Object("$TMP_DIR/test");
19916
19917 unlink("$TMP_DIR/test.c");
19918 unlink("$TMP_DIR/test");
19919 }
19920
19921 if(not $Arch) {
19922 exitStatus("Error", "can't check ARCH type");
19923 }
19924
19925 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19926}
19927
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019928sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019929{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019930 my $LibVersion = $_[0];
19931
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019932 my $Size = undef;
19933
19934 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019935 if(my $Arch = getArch($LibVersion))
19936 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019937 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019938 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019939 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019940 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19941 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019942 }
19943 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019944
19945 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019946 {
19947 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019948
19949 my $Cmd = $GCC_PATH." -E -dD empty.h";
19950 if(my $Opts = getGCC_Opts($LibVersion))
19951 { # user-defined options
19952 $Cmd .= " ".$Opts;
19953 }
19954
19955 chdir($TMP_DIR);
19956 my $Defines = `$Cmd`;
19957 chdir($ORIG_DIR);
19958
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019959 unlink("$TMP_DIR/empty.h");
19960
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019961 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19962 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019963 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019964 }
19965 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19966 { # GCC 3
19967 my $PTRDIFF = $1;
19968 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019969 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019970 }
19971 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019972 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019973 }
19974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019975 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019976
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019977 if(not $Size) {
19978 exitStatus("Error", "can't check WORD size");
19979 }
19980
19981 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019982}
19983
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019984sub getWordSize($)
19985{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019986 return $WORD_SIZE{$_[0]};
19987}
19988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019989sub majorVersion($)
19990{
19991 my $V = $_[0];
19992 return 0 if(not $V);
19993 my @VParts = split(/\./, $V);
19994 return $VParts[0];
19995}
19996
19997sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019998{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019999 my ($V1, $V2) = @_;
20000 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020001 my @V1Parts = split(/\./, $V1);
20002 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020003 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20004 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020005 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20006 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20007 }
20008 return -1 if($#V1Parts < $#V2Parts);
20009 return 1 if($#V1Parts > $#V2Parts);
20010 return 0;
20011}
20012
20013sub read_ABI_Dump($$)
20014{
20015 my ($LibVersion, $Path) = @_;
20016 return if(not $LibVersion or not -e $Path);
20017 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020018 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020019 { # input *.abi
20020 $FilePath = $Path;
20021 }
20022 else
20023 { # input *.abi.tar.gz
20024 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020025 if(not isDump_U($FilePath)) {
20026 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020028 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020029
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020030 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020031
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020032 my $Line = readLineNum($FilePath, 0);
20033 if($Line=~/xml/)
20034 { # XML format
20035 loadModule("XmlDump");
20036 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020037 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020038 else
20039 { # Perl Data::Dumper format (default)
20040 open(DUMP, $FilePath);
20041 local $/ = undef;
20042 my $Content = <DUMP>;
20043 close(DUMP);
20044
20045 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20046 { # remove temp file
20047 unlink($FilePath);
20048 }
20049 if($Content!~/};\s*\Z/) {
20050 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20051 }
20052 $ABI = eval($Content);
20053 if(not $ABI) {
20054 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020056 }
20057 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020058 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020059 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020060 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020061 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020062 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020063 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020064 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020065 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020066
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020067 if($ABI->{"PublicABI"}) {
20068 $UsedDump{$LibVersion}{"Public"} = 1;
20069 }
20070
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020071 if($ABI->{"ABI_DUMP_VERSION"})
20072 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020073 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020074 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020075 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020076 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020077 }
20078 else
20079 { # support for old ABI dumps
20080 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020081 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020082 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020084 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020085
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020086 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020087 {
20088 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 +040020089 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020090
20091 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20092 { # DWARF ABI Dump
20093 $UseConv_Real{$LibVersion}{"P"} = 1;
20094 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20095
20096 $UsedDump{$LibVersion}{"DWARF"} = 1;
20097
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020098 if(not $TargetComponent_Opt)
20099 {
20100 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20101 $TargetComponent = "module";
20102 }
20103 else {
20104 $TargetComponent = "object";
20105 }
20106 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020107 }
20108
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020109 if(not checkDump($LibVersion, "2.11"))
20110 { # old ABI dumps
20111 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020112 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020113 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020114 { # ABI dump created with --binary option
20115 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20116 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020117 else
20118 { # default
20119 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20120 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020121
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020122 if(defined $ABI->{"Mode"}
20123 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020124 { # --ext option
20125 $ExtendedCheck = 1;
20126 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020127 if($ABI->{"Extra"}) {
20128 $ExtraDump = 1;
20129 }
20130
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020131 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020132 {
20133 $UsedDump{$LibVersion}{"L"} = $Lang;
20134 setLanguage($LibVersion, $Lang);
20135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020136 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020137 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020138 }
20139 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020140 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020141 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020142 if(not $TInfo)
20143 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020144 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020145 }
20146 my %Tid_TDid = ();
20147 foreach my $TDid (keys(%{$TInfo}))
20148 {
20149 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20150 {
20151 $MAX_ID = $Tid if($Tid>$MAX_ID);
20152 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020153 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020154 }
20155 }
20156 my %NewID = ();
20157 foreach my $Tid (keys(%Tid_TDid))
20158 {
20159 my @TDids = keys(%{$Tid_TDid{$Tid}});
20160 if($#TDids>=1)
20161 {
20162 foreach my $TDid (@TDids)
20163 {
20164 if($TDid) {
20165 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20166 }
20167 else
20168 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020169 my $ID = ++$MAX_ID;
20170
20171 $NewID{$TDid}{$Tid} = $ID;
20172 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20173 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020174 }
20175 }
20176 }
20177 else
20178 {
20179 my $TDid = $TDids[0];
20180 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20181 }
20182 }
20183 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20184 {
20185 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20186 if(defined $Info{"BaseType"})
20187 {
20188 my $Bid = $Info{"BaseType"}{"Tid"};
20189 my $BDid = $Info{"BaseType"}{"TDid"};
20190 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020191 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020192 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20193 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20194 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020195 }
20196 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020198 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020199 read_Machine_DumpInfo($ABI, $LibVersion);
20200 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020201 if(not $SymbolInfo{$LibVersion})
20202 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020203 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020204 }
20205 if(not keys(%{$SymbolInfo{$LibVersion}}))
20206 { # validation of old-version dumps
20207 if(not $ExtendedCheck) {
20208 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20209 }
20210 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020211 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020212 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020213 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020214 else
20215 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020216 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020217 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020218 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020219 }
20220 if(not $DepSymbols)
20221 { # Cannot reconstruct DepSymbols. This may result in false
20222 # positives if the old dump is for library 2. Not a problem if
20223 # old dumps are only from old libraries.
20224 $DepSymbols = {};
20225 }
20226 foreach my $Symbol (keys(%{$DepSymbols})) {
20227 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020229 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020230 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020231
20232 if(my $V = $TargetVersion{$LibVersion}) {
20233 $Descriptor{$LibVersion}{"Version"} = $V;
20234 }
20235 else {
20236 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20237 }
20238
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020239 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020240 { # if not defined by -skip-types option
20241 if(defined $ABI->{"SkipTypes"})
20242 {
20243 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20244 {
20245 $SkipTypes{$LibVersion}{$TName} = 1;
20246 }
20247 }
20248 if(defined $ABI->{"OpaqueTypes"})
20249 { # support for old dumps
20250 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20251 {
20252 $SkipTypes{$LibVersion}{$TName} = 1;
20253 }
20254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020255 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020257 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020258 { # if not defined by -skip-symbols option
20259 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20260 if(not $SkipSymbols{$LibVersion})
20261 { # support for old dumps
20262 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20263 }
20264 if(not $SkipSymbols{$LibVersion})
20265 { # support for old dumps
20266 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020269 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020270
20271 if(not $TargetHeaders{$LibVersion})
20272 { # if not defined by -headers-list option
20273 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20274 }
20275
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020276 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020277 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020278 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020279
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020280 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020281 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020282 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020283
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020284 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020285 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020286
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020287 if(not checkDump($LibVersion, "2.10.1")
20288 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020289 { # support for old ABI dumps: added target headers
20290 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020291 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020292 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020293
20294 if(not $ABI->{"PublicABI"})
20295 {
20296 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20297 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20298 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020300 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020301 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020302 if(defined $ABI->{"GccConstants"})
20303 { # 3.0
20304 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20305 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20306 }
20307 }
20308
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020309 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020310 if(not $NestedNameSpaces{$LibVersion})
20311 { # support for old dumps
20312 # Cannot reconstruct NameSpaces. This may affect design
20313 # of the compatibility report.
20314 $NestedNameSpaces{$LibVersion} = {};
20315 }
20316 # target system type
20317 # needed to adopt HTML report
20318 if(not $DumpSystem)
20319 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020320 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020321 }
20322 # recreate environment
20323 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20324 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020325 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020326 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020327 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20328 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020329 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020330 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020331 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020332 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20333 {
20334 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20335 setLanguage($LibVersion, "C++");
20336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020337 }
20338 }
20339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020340 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20341 {
20342 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20343 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20344 }
20345 }
20346
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020347 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020348 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020349 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020350 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020351 {
20352 if(not $Symbol_Library{$LibVersion}{$MnglName}
20353 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20354 push(@VFunc, $MnglName);
20355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020356 }
20357 }
20358 translateSymbols(@VFunc, $LibVersion);
20359 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020360 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20361
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020362 if(not checkDump($LibVersion, "3.0"))
20363 { # support for old ABI dumps
20364 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20365 {
20366 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20367 {
20368 if(ref($BaseType) eq "HASH") {
20369 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20370 }
20371 }
20372 }
20373 }
20374
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020375 if(not checkDump($LibVersion, "3.2"))
20376 { # support for old ABI dumps
20377 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20378 {
20379 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20380 {
20381 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20382 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20383 }
20384 }
20385 }
20386
20387 # repair target headers list
20388 delete($TargetHeaders{$LibVersion});
20389 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020390 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20391 }
20392 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20393 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020394 }
20395
20396 # non-target constants from anon enums
20397 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20398 {
20399 if(not $ExtraDump
20400 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20401 {
20402 delete($Constants{$LibVersion}{$Name});
20403 }
20404 }
20405 }
20406
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020407 if(not checkDump($LibVersion, "2.20"))
20408 { # support for old ABI dumps
20409 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20410 {
20411 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20412
20413 if($TType=~/Struct|Union|Enum|Typedef/)
20414 { # repair complex types first
20415 next;
20416 }
20417
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020418 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020419 {
20420 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20421 if($BType=~/Struct|Union|Enum/i)
20422 {
20423 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20424 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20425 }
20426 }
20427 }
20428 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20429 {
20430 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20431 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20432 if($TType=~/Struct|Union|Enum/) {
20433 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20434 }
20435 }
20436 }
20437
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020438 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020439 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020440 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20441 { # support for old ABI dumps < 2.0 (ACC 1.22)
20442 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20443 {
20444 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20445 {
20446 if($Access ne "public") {
20447 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20448 }
20449 }
20450 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20451 }
20452 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20453 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020454 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20455 { # support for old ABI dumps
20456 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20457 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020458 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20459 { # DWARF ABI Dumps
20460 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20461 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020462 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20463 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20464 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020465
20466 # support for old formatting of type names
20467 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20468
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020469 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20470 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020471 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020472 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20473 {
20474 if($SubId eq $TypeId)
20475 { # Fix erroneus ABI dump
20476 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20477 next;
20478 }
20479
20480 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020482 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020483 if($TInfo{"Type"} eq "MethodPtr")
20484 {
20485 if(defined $TInfo{"Param"})
20486 { # support for old ABI dumps <= 1.17
20487 if(not defined $TInfo{"Param"}{"0"})
20488 {
20489 my $Max = keys(%{$TInfo{"Param"}});
20490 foreach my $Pos (1 .. $Max) {
20491 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20492 }
20493 delete($TInfo{"Param"}{$Max});
20494 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20495 }
20496 }
20497 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020498 if($TInfo{"BaseType"} eq $TypeId)
20499 { # fix ABI dump
20500 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20501 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020502
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020503 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020504 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020505 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020506 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020507 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20508 if(not $BName)
20509 { # broken type
20510 next;
20511 }
20512 if($TInfo{"Name"} eq $BName)
20513 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020514 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020515 next;
20516 }
20517 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20518 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020519 }
20520 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020521 }
20522 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20523 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020524 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020525 }
20526 }
20527
20528 if(not checkDump($LibVersion, "2.15"))
20529 { # support for old ABI dumps
20530 my %Dups = ();
20531 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20532 {
20533 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020535 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20536 { # remove template decls
20537 delete($SymbolInfo{$LibVersion}{$InfoId});
20538 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020540 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020541 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20542 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020543 { # templates
20544 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020545 }
20546 }
20547 }
20548
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020549 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20550 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020551 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20552 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20553 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20554 { # support for old ABI dumps (< 3.1)
20555 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20556 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20557 { # add "this" first parameter
20558 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20559 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20560
20561 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20562 {
20563 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20564 foreach my $Pos (reverse(0 .. $#Pos)) {
20565 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20566 }
20567 }
20568 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20569 }
20570 }
20571
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020572 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20573 { # ABI dumps have no mangled names for C-functions
20574 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20575 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020576 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20577 { # support for old ABI dumps
20578 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20579 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020580 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20581 { # DWARF ABI Dumps
20582 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20583 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020584 }
20585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 $Descriptor{$LibVersion}{"Dump"} = 1;
20587}
20588
20589sub read_Machine_DumpInfo($$)
20590{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020591 my ($ABI, $LibVersion) = @_;
20592 if($ABI->{"Arch"}) {
20593 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020594 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020595 if($ABI->{"WordSize"}) {
20596 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020597 }
20598 else
20599 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020600 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020601 }
20602 if(not $WORD_SIZE{$LibVersion})
20603 { # support for old dumps (<1.23)
20604 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20605 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020606 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020607 }
20608 else
20609 {
20610 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020611 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020613 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20614 { # any "pointer"-type
20615 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020616 last;
20617 }
20618 }
20619 if($PSize)
20620 { # a pointer type size
20621 $WORD_SIZE{$LibVersion} = $PSize;
20622 }
20623 else {
20624 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20625 }
20626 }
20627 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020628 if($ABI->{"GccVersion"}) {
20629 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020630 }
20631}
20632
20633sub read_Libs_DumpInfo($$)
20634{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020635 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020636 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20637 if(not $Library_Symbol{$LibVersion})
20638 { # support for old dumps
20639 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020641 if(keys(%{$Library_Symbol{$LibVersion}})
20642 and not $DumpAPI) {
20643 $Descriptor{$LibVersion}{"Libs"} = "OK";
20644 }
20645}
20646
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020647sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020648{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020649 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020650
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020651 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020652 and not $DumpAPI) {
20653 $Descriptor{$LibVersion}{"Headers"} = "OK";
20654 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020655 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020656 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020657 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020658 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020659 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020660
20661 if(keys(%{$ABI->{"Sources"}})
20662 and not $DumpAPI) {
20663 $Descriptor{$LibVersion}{"Sources"} = "OK";
20664 }
20665 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020666 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020667 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20668 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020670}
20671
20672sub find_libs($$$)
20673{
20674 my ($Path, $Type, $MaxDepth) = @_;
20675 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020676 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020677}
20678
20679sub createDescriptor($$)
20680{
20681 my ($LibVersion, $Path) = @_;
20682 if(not $LibVersion or not $Path
20683 or not -e $Path) {
20684 return "";
20685 }
20686 if(-d $Path)
20687 { # directory with headers files and shared objects
20688 return "
20689 <version>
20690 ".$TargetVersion{$LibVersion}."
20691 </version>
20692
20693 <headers>
20694 $Path
20695 </headers>
20696
20697 <libs>
20698 $Path
20699 </libs>";
20700 }
20701 else
20702 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020703 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020704 { # standard XML-descriptor
20705 return readFile($Path);
20706 }
20707 elsif(is_header($Path, 2, $LibVersion))
20708 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020709 $CheckHeadersOnly = 1;
20710
20711 if($LibVersion==1) {
20712 $TargetVersion{$LibVersion} = "X";
20713 }
20714
20715 if($LibVersion==2) {
20716 $TargetVersion{$LibVersion} = "Y";
20717 }
20718
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020719 return "
20720 <version>
20721 ".$TargetVersion{$LibVersion}."
20722 </version>
20723
20724 <headers>
20725 $Path
20726 </headers>
20727
20728 <libs>
20729 none
20730 </libs>";
20731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020732 else
20733 { # standard XML-descriptor
20734 return readFile($Path);
20735 }
20736 }
20737}
20738
20739sub detect_lib_default_paths()
20740{
20741 my %LPaths = ();
20742 if($OSgroup eq "bsd")
20743 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020744 if(my $LdConfig = get_CmdPath("ldconfig"))
20745 {
20746 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20747 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020748 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20749 {
20750 my $Name = "lib".$1;
20751 if(not defined $LPaths{$Name}) {
20752 $LPaths{$Name} = $2;
20753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020754 }
20755 }
20756 }
20757 else {
20758 printMsg("WARNING", "can't find ldconfig");
20759 }
20760 }
20761 else
20762 {
20763 if(my $LdConfig = get_CmdPath("ldconfig"))
20764 {
20765 if($SystemRoot and $OSgroup eq "linux")
20766 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20767 if(-e $SystemRoot."/etc/ld.so.conf") {
20768 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20769 }
20770 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020771 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20772 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020773 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20774 {
20775 my ($Name, $Path) = ($1, $2);
20776 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020777 if(not defined $LPaths{$Name})
20778 { # get first element from the list of available paths
20779
20780 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20781 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20782 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20783
20784 $LPaths{$Name} = $Path;
20785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020786 }
20787 }
20788 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020789 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020790 printMsg("WARNING", "can't find ldconfig");
20791 }
20792 }
20793 return \%LPaths;
20794}
20795
20796sub detect_bin_default_paths()
20797{
20798 my $EnvPaths = $ENV{"PATH"};
20799 if($OSgroup eq "beos") {
20800 $EnvPaths.=":".$ENV{"BETOOLS"};
20801 }
20802 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020803 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020804 {
20805 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020806 next if(not $Path);
20807 if($SystemRoot
20808 and $Path=~/\A\Q$SystemRoot\E\//)
20809 { # do NOT use binaries from target system
20810 next;
20811 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020812 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020813 }
20814}
20815
20816sub detect_inc_default_paths()
20817{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020818 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020819 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020820 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020821 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020822 next if(index($Line, "/cc1plus ")!=-1);
20823
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020824 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20825 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020826 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020828 if(index($Path, "c++")!=-1
20829 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020831 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020832 if(not defined $MAIN_CPP_DIR
20833 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20834 $MAIN_CPP_DIR = $Path;
20835 }
20836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020837 elsif(index($Path, "gcc")!=-1) {
20838 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020839 }
20840 else
20841 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020842 if($Path=~/local[\/\\]+include/)
20843 { # local paths
20844 next;
20845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020846 if($SystemRoot
20847 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20848 { # The GCC include path for user headers is not a part of the system root
20849 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20850 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20851 next;
20852 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020853 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020854 }
20855 }
20856 }
20857 unlink("$TMP_DIR/empty.h");
20858 return %DPaths;
20859}
20860
20861sub detect_default_paths($)
20862{
20863 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20864 my $Search = $_[0];
20865 if($Search!~/inc/) {
20866 $HSearch = 0;
20867 }
20868 if($Search!~/lib/) {
20869 $LSearch = 0;
20870 }
20871 if($Search!~/bin/) {
20872 $BSearch = 0;
20873 }
20874 if($Search!~/gcc/) {
20875 $GSearch = 0;
20876 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020877 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020878 { # <search_headers> section of the XML descriptor
20879 # do NOT search for systems headers
20880 $HSearch = 0;
20881 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020882 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020883 { # <search_libs> section of the XML descriptor
20884 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020885 $LSearch = 0;
20886 }
20887 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20888 { # additional search paths
20889 next if($Type eq "include" and not $HSearch);
20890 next if($Type eq "lib" and not $LSearch);
20891 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020892 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020893 }
20894 if($OSgroup ne "windows")
20895 { # unix-like
20896 foreach my $Type ("include", "lib", "bin")
20897 { # automatic detection of system "devel" directories
20898 next if($Type eq "include" and not $HSearch);
20899 next if($Type eq "lib" and not $LSearch);
20900 next if($Type eq "bin" and not $BSearch);
20901 my ($UsrDir, $RootDir) = ("/usr", "/");
20902 if($SystemRoot and $Type ne "bin")
20903 { # 1. search for target headers and libraries
20904 # 2. use host commands: ldconfig, readelf, etc.
20905 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20906 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020907 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020908 if(-d $RootDir."/".$Type)
20909 { # if "/lib" is symbolic link
20910 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020911 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020912 }
20913 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020914 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020915 }
20916 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020917 if(-d $UsrDir)
20918 {
20919 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020920 if(-d $UsrDir."/".$Type)
20921 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020922 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020923 }
20924 }
20925 }
20926 }
20927 if($BSearch)
20928 {
20929 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020930 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 }
20932 # check environment variables
20933 if($OSgroup eq "beos")
20934 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020935 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020937 if($_ eq ".") {
20938 next;
20939 }
20940 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20941 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20942 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020943 }
20944 }
20945 if($HSearch)
20946 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020947 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20948 split(/:|;/, $ENV{"BEINCLUDES"})
20949 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020950 }
20951 if($LSearch)
20952 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020953 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20954 split(/:|;/, $ENV{"BELIBRARIES"}),
20955 split(/:|;/, $ENV{"LIBRARY_PATH"})
20956 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020957 }
20958 }
20959 if($LSearch)
20960 { # using linker to get system paths
20961 if(my $LPaths = detect_lib_default_paths())
20962 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020963 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020964 foreach my $Name (keys(%{$LPaths}))
20965 {
20966 if($SystemRoot
20967 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20968 { # wrong ldconfig configuration
20969 # check your <sysroot>/etc/ld.so.conf
20970 next;
20971 }
20972 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020973 if(my $Dir = get_dirname($LPaths->{$Name})) {
20974 $Dirs{$Dir} = 1;
20975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020977 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020978 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020979 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020980 }
20981 if($BSearch)
20982 {
20983 if($CrossGcc)
20984 { # --cross-gcc=arm-linux-gcc
20985 if(-e $CrossGcc)
20986 { # absolute or relative path
20987 $GCC_PATH = get_abs_path($CrossGcc);
20988 }
20989 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20990 { # command name
20991 $GCC_PATH = $CrossGcc;
20992 }
20993 else {
20994 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20995 }
20996 if($GCC_PATH=~/\s/) {
20997 $GCC_PATH = "\"".$GCC_PATH."\"";
20998 }
20999 }
21000 }
21001 if($GSearch)
21002 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021003 if(not $CrossGcc)
21004 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021005 $GCC_PATH = get_CmdPath("gcc");
21006 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021007 if(not $GCC_PATH)
21008 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021009 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021010 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021011 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021012 { # select the latest version
21013 @GCCs = sort {$b cmp $a} @GCCs;
21014 if(check_gcc($GCCs[0], "3"))
21015 {
21016 $GCC_PATH = $GCCs[0];
21017 last;
21018 }
21019 }
21020 }
21021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021022 if(not $GCC_PATH) {
21023 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21024 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021025
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021026 my $GCC_Ver = get_dumpversion($GCC_PATH);
21027 if($GCC_Ver eq "4.8")
21028 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21029 my $Info = `$GCC_PATH --version`;
21030
21031 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21032 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21033 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21034 $GCC_Ver = $2;
21035 }
21036 }
21037
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021038 if($OStarget=~/macos/)
21039 {
21040 my $Info = `$GCC_PATH --version`;
21041
21042 if($Info=~/clang/i) {
21043 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21044 }
21045 }
21046
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021047 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021049 my $GccTarget = get_dumpmachine($GCC_PATH);
21050
21051 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021052 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021053 $OStarget = "linux";
21054 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021055 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021056 elsif($GccTarget=~/symbian/)
21057 {
21058 $OStarget = "symbian";
21059 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21060 }
21061
21062 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21063
21064 # check GCC version
21065 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21066 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021067 # introduced in 4.8 and fixed in 4.8.3
21068 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.");
21069
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021070 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021071 }
21072 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021073 else {
21074 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021075 }
21076 }
21077 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021078 {
21079 # GCC standard paths
21080 if($GCC_PATH and not $NoStdInc)
21081 {
21082 my %DPaths = detect_inc_default_paths();
21083 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21084 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21085 @DefaultIncPaths = @{$DPaths{"Inc"}};
21086 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21087 }
21088
21089 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021090 my $IncPath = "/usr/include";
21091 if($SystemRoot) {
21092 $IncPath = $SystemRoot.$IncPath;
21093 }
21094 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021095 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021096 }
21097 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021098
21099 if($ExtraInfo)
21100 {
21101 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21102 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021104}
21105
21106sub getLIB_EXT($)
21107{
21108 my $Target = $_[0];
21109 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21110 return $Ext;
21111 }
21112 return $OS_LibExt{$LIB_TYPE}{"default"};
21113}
21114
21115sub getAR_EXT($)
21116{
21117 my $Target = $_[0];
21118 if(my $Ext = $OS_Archive{$Target}) {
21119 return $Ext;
21120 }
21121 return $OS_Archive{"default"};
21122}
21123
21124sub get_dumpversion($)
21125{
21126 my $Cmd = $_[0];
21127 return "" if(not $Cmd);
21128 if($Cache{"get_dumpversion"}{$Cmd}) {
21129 return $Cache{"get_dumpversion"}{$Cmd};
21130 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021131 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021132 chomp($V);
21133 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21134}
21135
21136sub get_dumpmachine($)
21137{
21138 my $Cmd = $_[0];
21139 return "" if(not $Cmd);
21140 if($Cache{"get_dumpmachine"}{$Cmd}) {
21141 return $Cache{"get_dumpmachine"}{$Cmd};
21142 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021143 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021144 chomp($Machine);
21145 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21146}
21147
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021148sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021149{
21150 my $Cmd = $_[0];
21151 return "" if(not $Cmd);
21152 my @Options = (
21153 "--version",
21154 "-help"
21155 );
21156 foreach my $Opt (@Options)
21157 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021158 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 if($Info) {
21160 return 1;
21161 }
21162 }
21163 return 0;
21164}
21165
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021166sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021167{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021168 my ($Cmd, $ReqVer) = @_;
21169 return 0 if(not $Cmd or not $ReqVer);
21170 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21171 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021173 if(my $GccVer = get_dumpversion($Cmd))
21174 {
21175 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21176 if(cmpVersions($GccVer, $ReqVer)>=0) {
21177 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21178 }
21179 }
21180 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181}
21182
21183sub get_depth($)
21184{
21185 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021186 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021187 }
21188 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21189}
21190
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021191sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021192{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021193 return if($Cache{"registerGccHeaders"}); # this function should be called once
21194
21195 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021196 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021197 my @Headers = cmd_find($Path,"f");
21198 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21199 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021200 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021201 my $FileName = get_filename($HPath);
21202 if(not defined $DefaultGccHeader{$FileName})
21203 { # skip duplicated
21204 $DefaultGccHeader{$FileName} = $HPath;
21205 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021206 }
21207 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021208 $Cache{"registerGccHeaders"} = 1;
21209}
21210
21211sub registerCppHeaders()
21212{
21213 return if($Cache{"registerCppHeaders"}); # this function should be called once
21214
21215 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021216 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021217 my @Headers = cmd_find($CppDir,"f");
21218 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21219 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021220 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021221 my $FileName = get_filename($Path);
21222 if(not defined $DefaultCppHeader{$FileName})
21223 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021224 $DefaultCppHeader{$FileName} = $Path;
21225 }
21226 }
21227 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021228 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021229}
21230
21231sub parse_libname($$$)
21232{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021233 return "" if(not $_[0]);
21234 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21235 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021236 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021237 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21238}
21239
21240sub parse_libname_I($$$)
21241{
21242 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021244 if($Target eq "symbian") {
21245 return parse_libname_symbian($Name, $Type);
21246 }
21247 elsif($Target eq "windows") {
21248 return parse_libname_windows($Name, $Type);
21249 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021250
21251 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021252 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021253 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021254 { # libSDL-1.2.so.0.7.1
21255 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021256 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021257 if($Type eq "name")
21258 { # libSDL-1.2
21259 # libwbxml2
21260 return $2;
21261 }
21262 elsif($Type eq "name+ext")
21263 { # libSDL-1.2.so
21264 # libwbxml2.so
21265 return $1;
21266 }
21267 elsif($Type eq "version")
21268 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021269 if(defined $7
21270 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021271 { # 0.7.1
21272 return $7;
21273 }
21274 else
21275 { # libc-2.5.so (=>2.5 version)
21276 my $MV = $5;
21277 $MV=~s/\A[\-\_]+//g;
21278 return $MV;
21279 }
21280 }
21281 elsif($Type eq "short")
21282 { # libSDL
21283 # libwbxml2
21284 return $3;
21285 }
21286 elsif($Type eq "shortest")
21287 { # SDL
21288 # wbxml
21289 return shortest_name($3);
21290 }
21291 }
21292 return "";# error
21293}
21294
21295sub parse_libname_symbian($$)
21296{
21297 my ($Name, $Type) = @_;
21298 my $Ext = getLIB_EXT("symbian");
21299 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21300 { # libpthread{00010001}.dso
21301 if($Type eq "name")
21302 { # libpthread{00010001}
21303 return $2;
21304 }
21305 elsif($Type eq "name+ext")
21306 { # libpthread{00010001}.dso
21307 return $1;
21308 }
21309 elsif($Type eq "version")
21310 { # 00010001
21311 my $V = $4;
21312 $V=~s/\{(.+)\}/$1/;
21313 return $V;
21314 }
21315 elsif($Type eq "short")
21316 { # libpthread
21317 return $3;
21318 }
21319 elsif($Type eq "shortest")
21320 { # pthread
21321 return shortest_name($3);
21322 }
21323 }
21324 return "";# error
21325}
21326
21327sub parse_libname_windows($$)
21328{
21329 my ($Name, $Type) = @_;
21330 my $Ext = getLIB_EXT("windows");
21331 if($Name=~/((.+?)\.$Ext)\Z/)
21332 { # netapi32.dll
21333 if($Type eq "name")
21334 { # netapi32
21335 return $2;
21336 }
21337 elsif($Type eq "name+ext")
21338 { # netapi32.dll
21339 return $1;
21340 }
21341 elsif($Type eq "version")
21342 { # DLL version embedded
21343 # at binary-level
21344 return "";
21345 }
21346 elsif($Type eq "short")
21347 { # netapi32
21348 return $2;
21349 }
21350 elsif($Type eq "shortest")
21351 { # netapi
21352 return shortest_name($2);
21353 }
21354 }
21355 return "";# error
21356}
21357
21358sub shortest_name($)
21359{
21360 my $Name = $_[0];
21361 # remove prefix
21362 $Name=~s/\A(lib|open)//;
21363 # remove suffix
21364 $Name=~s/[\W\d_]+\Z//i;
21365 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21366 return $Name;
21367}
21368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021369sub createSymbolsList($$$$$)
21370{
21371 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021373 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021374 prepareSymbols(1);
21375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021376 my %SymbolHeaderLib = ();
21377 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021378
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021379 # Get List
21380 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21381 {
21382 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021383 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021384 next;
21385 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021386 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021387 { # skip other symbols
21388 next;
21389 }
21390 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21391 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021392 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021393 next;
21394 }
21395 my $DyLib = $Symbol_Library{1}{$Symbol};
21396 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021397 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021398 next;
21399 }
21400 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21401 $Total+=1;
21402 }
21403 # Draw List
21404 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21405 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21406 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21407 {
21408 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21409 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021410 my %NS_Symbol = ();
21411 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021412 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021413 }
21414 foreach my $NameSpace (sort keys(%NS_Symbol))
21415 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021416 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021417 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21418 foreach my $Symbol (@SortedInterfaces)
21419 {
21420 my $SubReport = "";
21421 my $Signature = get_Signature($Symbol, 1);
21422 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021423 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021424 }
21425 if($Symbol=~/\A(_Z|\?)/)
21426 {
21427 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021428 $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 +040021429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021430 else {
21431 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21432 }
21433 }
21434 else
21435 {
21436 if($Signature) {
21437 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21438 }
21439 else {
21440 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21441 }
21442 }
21443 $SYMBOLS_LIST .= $SubReport;
21444 }
21445 }
21446 $SYMBOLS_LIST .= "<br/>\n";
21447 }
21448 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021449 # clear info
21450 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21451 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21452 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21453 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021454 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021455 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021456 my $CssStyles = readModule("Styles", "SymbolsList.css");
21457 my $JScripts = readModule("Scripts", "Sections.js");
21458 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021459 my $Title = "$LName: public symbols";
21460 my $Keywords = "$LName, API, symbols";
21461 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021462 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021463 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021464 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021465 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021466 writeFile($SaveTo, $SYMBOLS_LIST);
21467}
21468
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021469sub add_target_libs($)
21470{
21471 foreach (@{$_[0]}) {
21472 $TargetLibs{$_} = 1;
21473 }
21474}
21475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021476sub is_target_lib($)
21477{
21478 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021479 if(not $LName) {
21480 return 0;
21481 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021482 if($TargetLibraryName
21483 and $LName!~/\Q$TargetLibraryName\E/) {
21484 return 0;
21485 }
21486 if(keys(%TargetLibs)
21487 and not $TargetLibs{$LName}
21488 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21489 return 0;
21490 }
21491 return 1;
21492}
21493
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021494sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021495{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021496 my ($H, $V) = @_;
21497 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021498 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021499 if($TargetHeaders{$V}{$H}) {
21500 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021501 }
21502 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021503 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021504}
21505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021506sub readLibs($)
21507{
21508 my $LibVersion = $_[0];
21509 if($OStarget eq "windows")
21510 { # dumpbin.exe will crash
21511 # without VS Environment
21512 check_win32_env();
21513 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021514 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021515 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021516 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021517}
21518
21519sub dump_sorting($)
21520{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021521 my $Hash = $_[0];
21522 return [] if(not $Hash);
21523 my @Keys = keys(%{$Hash});
21524 return [] if($#Keys<0);
21525 if($Keys[0]=~/\A\d+\Z/)
21526 { # numbers
21527 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021528 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021529 else
21530 { # strings
21531 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021532 }
21533}
21534
21535sub printMsg($$)
21536{
21537 my ($Type, $Msg) = @_;
21538 if($Type!~/\AINFO/) {
21539 $Msg = $Type.": ".$Msg;
21540 }
21541 if($Type!~/_C\Z/) {
21542 $Msg .= "\n";
21543 }
21544 if($Quiet)
21545 { # --quiet option
21546 appendFile($COMMON_LOG_PATH, $Msg);
21547 }
21548 else
21549 {
21550 if($Type eq "ERROR") {
21551 print STDERR $Msg;
21552 }
21553 else {
21554 print $Msg;
21555 }
21556 }
21557}
21558
21559sub exitStatus($$)
21560{
21561 my ($Code, $Msg) = @_;
21562 printMsg("ERROR", $Msg);
21563 exit($ERROR_CODE{$Code});
21564}
21565
21566sub exitReport()
21567{ # the tool has run without any errors
21568 printReport();
21569 if($COMPILE_ERRORS)
21570 { # errors in headers may add false positives/negatives
21571 exit($ERROR_CODE{"Compile_Error"});
21572 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021573 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21574 { # --binary
21575 exit($ERROR_CODE{"Incompatible"});
21576 }
21577 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21578 { # --source
21579 exit($ERROR_CODE{"Incompatible"});
21580 }
21581 elsif($RESULT{"Source"}{"Problems"}
21582 or $RESULT{"Binary"}{"Problems"})
21583 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021584 exit($ERROR_CODE{"Incompatible"});
21585 }
21586 else {
21587 exit($ERROR_CODE{"Compatible"});
21588 }
21589}
21590
21591sub readRules($)
21592{
21593 my $Kind = $_[0];
21594 if(not -f $RULES_PATH{$Kind}) {
21595 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21596 }
21597 my $Content = readFile($RULES_PATH{$Kind});
21598 while(my $Rule = parseTag(\$Content, "rule"))
21599 {
21600 my $RId = parseTag(\$Rule, "id");
21601 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21602 foreach my $Prop (@Properties) {
21603 if(my $Value = parseTag(\$Rule, lc($Prop)))
21604 {
21605 $Value=~s/\n[ ]*//;
21606 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21607 }
21608 }
21609 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21610 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21611 }
21612 else {
21613 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21614 }
21615 }
21616}
21617
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021618sub getReportPath($)
21619{
21620 my $Level = $_[0];
21621 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21622 if($Level eq "Binary")
21623 {
21624 if($BinaryReportPath)
21625 { # --bin-report-path
21626 return $BinaryReportPath;
21627 }
21628 elsif($OutputReportPath)
21629 { # --report-path
21630 return $OutputReportPath;
21631 }
21632 else
21633 { # default
21634 return $Dir."/abi_compat_report.$ReportFormat";
21635 }
21636 }
21637 elsif($Level eq "Source")
21638 {
21639 if($SourceReportPath)
21640 { # --src-report-path
21641 return $SourceReportPath;
21642 }
21643 elsif($OutputReportPath)
21644 { # --report-path
21645 return $OutputReportPath;
21646 }
21647 else
21648 { # default
21649 return $Dir."/src_compat_report.$ReportFormat";
21650 }
21651 }
21652 else
21653 {
21654 if($OutputReportPath)
21655 { # --report-path
21656 return $OutputReportPath;
21657 }
21658 else
21659 { # default
21660 return $Dir."/compat_report.$ReportFormat";
21661 }
21662 }
21663}
21664
21665sub printStatMsg($)
21666{
21667 my $Level = $_[0];
21668 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21669}
21670
21671sub listAffected($)
21672{
21673 my $Level = $_[0];
21674 my $List = "";
21675 foreach (keys(%{$TotalAffected{$Level}}))
21676 {
21677 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21678 { # skip "Low"-severity problems
21679 next;
21680 }
21681 $List .= "$_\n";
21682 }
21683 my $Dir = get_dirname(getReportPath($Level));
21684 if($Level eq "Binary") {
21685 writeFile($Dir."/abi_affected.txt", $List);
21686 }
21687 elsif($Level eq "Source") {
21688 writeFile($Dir."/src_affected.txt", $List);
21689 }
21690}
21691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021692sub printReport()
21693{
21694 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021695 createReport();
21696 if($JoinReport or $DoubleReport)
21697 {
21698 if($RESULT{"Binary"}{"Problems"}
21699 or $RESULT{"Source"}{"Problems"}) {
21700 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021701 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021702 else {
21703 printMsg("INFO", "result: COMPATIBLE");
21704 }
21705 printStatMsg("Binary");
21706 printStatMsg("Source");
21707 if($ListAffected)
21708 { # --list-affected
21709 listAffected("Binary");
21710 listAffected("Source");
21711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021712 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021713 elsif($BinaryOnly)
21714 {
21715 if($RESULT{"Binary"}{"Problems"}) {
21716 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21717 }
21718 else {
21719 printMsg("INFO", "result: COMPATIBLE");
21720 }
21721 printStatMsg("Binary");
21722 if($ListAffected)
21723 { # --list-affected
21724 listAffected("Binary");
21725 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021726 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021727 elsif($SourceOnly)
21728 {
21729 if($RESULT{"Source"}{"Problems"}) {
21730 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21731 }
21732 else {
21733 printMsg("INFO", "result: COMPATIBLE");
21734 }
21735 printStatMsg("Source");
21736 if($ListAffected)
21737 { # --list-affected
21738 listAffected("Source");
21739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021740 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021741 if($StdOut)
21742 {
21743 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021744 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021745 printMsg("INFO", "compatibility report has been generated to stdout");
21746 }
21747 else
21748 { # default
21749 printMsg("INFO", "compatibility reports have been generated to stdout");
21750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021751 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021752 else
21753 {
21754 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021755 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021756 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21757 }
21758 elsif($DoubleReport)
21759 { # default
21760 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21761 }
21762 elsif($BinaryOnly)
21763 { # --binary
21764 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21765 }
21766 elsif($SourceOnly)
21767 { # --source
21768 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021770 }
21771}
21772
21773sub check_win32_env()
21774{
21775 if(not $ENV{"DevEnvDir"}
21776 or not $ENV{"LIB"}) {
21777 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21778 }
21779}
21780
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021781sub diffSets($$)
21782{
21783 my ($S1, $S2) = @_;
21784 my @SK1 = keys(%{$S1});
21785 my @SK2 = keys(%{$S2});
21786 if($#SK1!=$#SK2) {
21787 return 1;
21788 }
21789 foreach my $K1 (@SK1)
21790 {
21791 if(not defined $S2->{$K1}) {
21792 return 1;
21793 }
21794 }
21795 return 0;
21796}
21797
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021798sub defaultDumpPath($$)
21799{
21800 my ($N, $V) = @_;
21801 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21802}
21803
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021804sub create_ABI_Dump()
21805{
21806 if(not -e $DumpAPI) {
21807 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21808 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021809
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021810 if(isDump($DumpAPI)) {
21811 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021812 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021813 else {
21814 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021815 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021816
21817 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021818 { # set to default: N
21819 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021820 }
21821
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021822 initLogging(1);
21823 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021824
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021825 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021826 if($OutputDumpPath)
21827 { # user defined path
21828 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021829 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021830 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21831
21832 if(not $Archive and not $StdOut)
21833 { # check archive utilities
21834 if($OSgroup eq "windows")
21835 { # using zip
21836 my $ZipCmd = get_CmdPath("zip");
21837 if(not $ZipCmd) {
21838 exitStatus("Not_Found", "can't find \"zip\"");
21839 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021840 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021841 else
21842 { # using tar and gzip
21843 my $TarCmd = get_CmdPath("tar");
21844 if(not $TarCmd) {
21845 exitStatus("Not_Found", "can't find \"tar\"");
21846 }
21847 my $GzipCmd = get_CmdPath("gzip");
21848 if(not $GzipCmd) {
21849 exitStatus("Not_Found", "can't find \"gzip\"");
21850 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021851 }
21852 }
21853
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021854 if(not $Descriptor{1}{"Dump"})
21855 {
21856 if(not $CheckHeadersOnly) {
21857 readLibs(1);
21858 }
21859 if($CheckHeadersOnly) {
21860 setLanguage(1, "C++");
21861 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021862 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021863 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021864 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021865 if(not $Descriptor{1}{"Dump"})
21866 {
21867 if($Descriptor{1}{"Headers"}) {
21868 readHeaders(1);
21869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021870 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021871 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021872 if(not keys(%{$SymbolInfo{1}}))
21873 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021874 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021875 {
21876 if($CheckHeadersOnly) {
21877 exitStatus("Empty_Set", "the set of public symbols is empty");
21878 }
21879 else {
21880 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21881 }
21882 }
21883 }
21884 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021885 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21887 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021888 if($ExtraDump)
21889 { # add unmangled names to the ABI dump
21890 my @Names = ();
21891 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21892 {
21893 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21894 push(@Names, $MnglName);
21895 }
21896 }
21897 translateSymbols(@Names, 1);
21898 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21899 {
21900 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21901 {
21902 if(my $Unmangled = $tr_name{$MnglName})
21903 {
21904 if($MnglName ne $Unmangled) {
21905 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21906 }
21907 }
21908 }
21909 }
21910 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021911
21912 my %GccConstants = (); # built-in GCC constants
21913 foreach my $Name (keys(%{$Constants{1}}))
21914 {
21915 if(not defined $Constants{1}{$Name}{"Header"})
21916 {
21917 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21918 delete($Constants{1}{$Name});
21919 }
21920 }
21921
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021922 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021923 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021924 "TypeInfo" => $TypeInfo{1},
21925 "SymbolInfo" => $SymbolInfo{1},
21926 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021927 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021928 "SymbolVersion" => $SymVer{1},
21929 "LibraryVersion" => $Descriptor{1}{"Version"},
21930 "LibraryName" => $TargetLibraryName,
21931 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021932 "SkipTypes" => $SkipTypes{1},
21933 "SkipSymbols" => $SkipSymbols{1},
21934 "SkipNameSpaces" => $SkipNameSpaces{1},
21935 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021936 "Headers" => \%HeadersInfo,
21937 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021938 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021939 "NameSpaces" => $NestedNameSpaces{1},
21940 "Target" => $OStarget,
21941 "Arch" => getArch(1),
21942 "WordSize" => $WORD_SIZE{1},
21943 "GccVersion" => get_dumpversion($GCC_PATH),
21944 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21945 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21946 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021947 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021948 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021949 }
21950 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021951 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021953 if($ExtendedCheck)
21954 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021955 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021956 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021957 if($BinaryOnly)
21958 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021959 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021960 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021961 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021962 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021963 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021964 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21965 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021966 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021967
21968 my $ABI_DUMP = "";
21969 if($UseXML)
21970 {
21971 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021972 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021974 else
21975 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021976 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021978 if($StdOut)
21979 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021980 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021981 printMsg("INFO", "ABI dump has been generated to stdout");
21982 return;
21983 }
21984 else
21985 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021986 my ($DDir, $DName) = separate_path($DumpPath);
21987 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021988 if(not $Archive) {
21989 $DPath = $DumpPath;
21990 }
21991
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021993
21994 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021995 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021996 close(DUMP);
21997
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021998 if(not -s $DPath) {
21999 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22000 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022001 if($Archive) {
22002 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022003 }
22004
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022005 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022006 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022007 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022008 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022009 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022010 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022011 # 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 +040022012 }
22013}
22014
22015sub quickEmptyReports()
22016{ # Quick "empty" reports
22017 # 4 times faster than merging equal dumps
22018 # NOTE: the dump contains the "LibraryVersion" attribute
22019 # if you change the version, then your dump will be different
22020 # OVERCOME: use -v1 and v2 options for comparing dumps
22021 # and don't change version in the XML descriptor (and dumps)
22022 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22023 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22024 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022025 my $FilePath1 = $Descriptor{1}{"Path"};
22026 my $FilePath2 = $Descriptor{2}{"Path"};
22027
22028 if(not isDump_U($FilePath1)) {
22029 $FilePath1 = unpackDump($FilePath1);
22030 }
22031
22032 if(not isDump_U($FilePath2)) {
22033 $FilePath2 = unpackDump($FilePath2);
22034 }
22035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022036 if($FilePath1 and $FilePath2)
22037 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022038 my $Line = readLineNum($FilePath1, 0);
22039 if($Line=~/xml/)
22040 { # XML format
22041 # is not supported yet
22042 return;
22043 }
22044
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022045 local $/ = undef;
22046
22047 open(DUMP1, $FilePath1);
22048 my $Content1 = <DUMP1>;
22049 close(DUMP1);
22050
22051 open(DUMP2, $FilePath2);
22052 my $Content2 = <DUMP2>;
22053 close(DUMP2);
22054
22055 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022057 # clean memory
22058 undef $Content2;
22059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022060 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022061 my $ABIdump = eval($Content1);
22062
22063 # clean memory
22064 undef $Content1;
22065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022066 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022067 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 +040022068 }
22069 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022070 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022071 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22072 }
22073 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022074 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022075 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22076 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022077 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022078 read_Libs_DumpInfo($ABIdump, 1);
22079 read_Machine_DumpInfo($ABIdump, 1);
22080 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022081
22082 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22083 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22084
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022085 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22086 {
22087 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22088 {
22089 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22090 next;
22091 }
22092 }
22093
22094 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22095 if($Access ne "private")
22096 {
22097 $CheckedSymbols{"Binary"}{$S} = 1;
22098 $CheckedSymbols{"Source"}{$S} = 1;
22099 }
22100 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022101
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022102 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22103 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22104 exitReport();
22105 }
22106 }
22107 }
22108}
22109
22110sub initLogging($)
22111{
22112 my $LibVersion = $_[0];
22113 # create log directory
22114 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22115 if($OutputLogPath{$LibVersion})
22116 { # user-defined by -log-path option
22117 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22118 }
22119 if($LogMode ne "n") {
22120 mkpath($LOG_DIR);
22121 }
22122 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022123 if($Debug)
22124 { # debug directory
22125 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022126
22127 if(not $ExtraInfo)
22128 { # enable --extra-info
22129 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022132 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022133}
22134
22135sub writeLog($$)
22136{
22137 my ($LibVersion, $Msg) = @_;
22138 if($LogMode ne "n") {
22139 appendFile($LOG_PATH{$LibVersion}, $Msg);
22140 }
22141}
22142
22143sub resetLogging($)
22144{
22145 my $LibVersion = $_[0];
22146 if($LogMode!~/a|n/)
22147 { # remove old log
22148 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022149 if($Debug) {
22150 rmtree($DEBUG_PATH{$LibVersion});
22151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022152 }
22153}
22154
22155sub printErrorLog($)
22156{
22157 my $LibVersion = $_[0];
22158 if($LogMode ne "n") {
22159 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22160 }
22161}
22162
22163sub isDump($)
22164{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022165 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22166 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022167 return $1;
22168 }
22169 return 0;
22170}
22171
22172sub isDump_U($)
22173{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022174 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022175 return $1;
22176 }
22177 return 0;
22178}
22179
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022180sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181{
22182 # read input XML descriptors or ABI dumps
22183 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022184 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022185 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022186 if(not -e $Descriptor{1}{"Path"}) {
22187 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022188 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022190 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022191 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022192 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022193 if(not -e $Descriptor{2}{"Path"}) {
22194 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022197 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022198 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022199 and isDump($Descriptor{2}{"Path"}))
22200 { # optimization: equal ABI dumps
22201 quickEmptyReports();
22202 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022204 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022205
22206 if(isDump($Descriptor{1}{"Path"})) {
22207 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022208 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022209 else {
22210 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22211 }
22212
22213 if(isDump($Descriptor{2}{"Path"})) {
22214 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22215 }
22216 else {
22217 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022218 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022219
22220 if(not $Descriptor{1}{"Version"})
22221 { # set to default: X
22222 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022223 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022224 }
22225
22226 if(not $Descriptor{2}{"Version"})
22227 { # set to default: Y
22228 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022229 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022230 }
22231
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022232 if(not $UsedDump{1}{"V"}) {
22233 initLogging(1);
22234 }
22235
22236 if(not $UsedDump{2}{"V"}) {
22237 initLogging(2);
22238 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022239
22240 # check input data
22241 if(not $Descriptor{1}{"Headers"}) {
22242 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022243 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022244 if(not $Descriptor{2}{"Headers"}) {
22245 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022246 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022247
22248 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022249 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022250 if(not $Descriptor{1}{"Libs"}) {
22251 exitStatus("Error", "can't find libraries info in descriptor d1");
22252 }
22253 if(not $Descriptor{2}{"Libs"}) {
22254 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022255 }
22256 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022257
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022258 if($UseDumps)
22259 { # --use-dumps
22260 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022261 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22262 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022263
22264 unlink($DumpPath1);
22265 unlink($DumpPath2);
22266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022267 my $pid = fork();
22268 if($pid)
22269 { # dump on two CPU cores
22270 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22271 if($RelativeDirectory{1}) {
22272 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22273 }
22274 if($OutputLogPath{1}) {
22275 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22276 }
22277 if($CrossGcc) {
22278 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22279 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022280 if($Quiet)
22281 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022282 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022283 @PARAMS = (@PARAMS, "-logging-mode", "a");
22284 }
22285 elsif($LogMode and $LogMode ne "w")
22286 { # "w" is default
22287 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022288 }
22289 if($ExtendedCheck) {
22290 @PARAMS = (@PARAMS, "-extended");
22291 }
22292 if($UserLang) {
22293 @PARAMS = (@PARAMS, "-lang", $UserLang);
22294 }
22295 if($TargetVersion{1}) {
22296 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22297 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022298 if($BinaryOnly) {
22299 @PARAMS = (@PARAMS, "-binary");
22300 }
22301 if($SourceOnly) {
22302 @PARAMS = (@PARAMS, "-source");
22303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022304 if($SortDump) {
22305 @PARAMS = (@PARAMS, "-sort");
22306 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022307 if($DumpFormat and $DumpFormat ne "perl") {
22308 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22309 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022310 if($CheckHeadersOnly) {
22311 @PARAMS = (@PARAMS, "-headers-only");
22312 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022313 if($Debug)
22314 {
22315 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022316 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022318 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022319 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 exit(1);
22321 }
22322 }
22323 else
22324 { # child
22325 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22326 if($RelativeDirectory{2}) {
22327 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22328 }
22329 if($OutputLogPath{2}) {
22330 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22331 }
22332 if($CrossGcc) {
22333 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22334 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022335 if($Quiet)
22336 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022337 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022338 @PARAMS = (@PARAMS, "-logging-mode", "a");
22339 }
22340 elsif($LogMode and $LogMode ne "w")
22341 { # "w" is default
22342 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022343 }
22344 if($ExtendedCheck) {
22345 @PARAMS = (@PARAMS, "-extended");
22346 }
22347 if($UserLang) {
22348 @PARAMS = (@PARAMS, "-lang", $UserLang);
22349 }
22350 if($TargetVersion{2}) {
22351 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22352 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022353 if($BinaryOnly) {
22354 @PARAMS = (@PARAMS, "-binary");
22355 }
22356 if($SourceOnly) {
22357 @PARAMS = (@PARAMS, "-source");
22358 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022359 if($SortDump) {
22360 @PARAMS = (@PARAMS, "-sort");
22361 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022362 if($DumpFormat and $DumpFormat ne "perl") {
22363 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22364 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022365 if($CheckHeadersOnly) {
22366 @PARAMS = (@PARAMS, "-headers-only");
22367 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022368 if($Debug)
22369 {
22370 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022371 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022373 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022374 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022375 exit(1);
22376 }
22377 else {
22378 exit(0);
22379 }
22380 }
22381 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022383 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022384 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22385 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022386 if($TargetTitle ne $TargetLibraryName) {
22387 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022388 }
22389 if($ShowRetVal) {
22390 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22391 }
22392 if($CrossGcc) {
22393 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22394 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022395 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22396 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022397 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022398 }
22399 if($ReportFormat and $ReportFormat ne "html")
22400 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022401 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22402 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022403 if($OutputReportPath) {
22404 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22405 }
22406 if($BinaryReportPath) {
22407 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22408 }
22409 if($SourceReportPath) {
22410 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22411 }
22412 if($LoggingPath) {
22413 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22414 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022415 if($CheckHeadersOnly) {
22416 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22417 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022418 if($BinaryOnly) {
22419 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22420 }
22421 if($SourceOnly) {
22422 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22423 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022424 if($Debug)
22425 {
22426 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22427 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022429 system("perl", $0, @CMP_PARAMS);
22430 exit($?>>8);
22431 }
22432 if(not $Descriptor{1}{"Dump"}
22433 or not $Descriptor{2}{"Dump"})
22434 { # need GCC toolchain to analyze
22435 # header files and libraries
22436 detect_default_paths("inc|lib|gcc");
22437 }
22438 if(not $Descriptor{1}{"Dump"})
22439 {
22440 if(not $CheckHeadersOnly) {
22441 readLibs(1);
22442 }
22443 if($CheckHeadersOnly) {
22444 setLanguage(1, "C++");
22445 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022446 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022447 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022448 }
22449 if(not $Descriptor{2}{"Dump"})
22450 {
22451 if(not $CheckHeadersOnly) {
22452 readLibs(2);
22453 }
22454 if($CheckHeadersOnly) {
22455 setLanguage(2, "C++");
22456 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022457 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022458 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022459 }
22460 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22461 { # support for old ABI dumps
22462 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022463 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022464 {
22465 $WORD_SIZE{1} = $WORD_SIZE{2};
22466 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22467 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022468 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022469 {
22470 $WORD_SIZE{2} = $WORD_SIZE{1};
22471 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22472 }
22473 }
22474 elsif(not $WORD_SIZE{1}
22475 and not $WORD_SIZE{2})
22476 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022477 $WORD_SIZE{1} = "4";
22478 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022479 }
22480 if($Descriptor{1}{"Dump"})
22481 { # support for old ABI dumps
22482 prepareTypes(1);
22483 }
22484 if($Descriptor{2}{"Dump"})
22485 { # support for old ABI dumps
22486 prepareTypes(2);
22487 }
22488 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22489 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22490 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022491 # process input data
22492 if($Descriptor{1}{"Headers"}
22493 and not $Descriptor{1}{"Dump"}) {
22494 readHeaders(1);
22495 }
22496 if($Descriptor{2}{"Headers"}
22497 and not $Descriptor{2}{"Dump"}) {
22498 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022499 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022500
22501 # clean memory
22502 %SystemHeaders = ();
22503 %mangled_name_gcc = ();
22504
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022505 prepareSymbols(1);
22506 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022507
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022508 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022509 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022510
22511 # Virtual Tables
22512 registerVTable(1);
22513 registerVTable(2);
22514
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022515 if(not checkDump(1, "1.22")
22516 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022517 { # support for old ABI dumps
22518 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22519 {
22520 if($ClassName=~/</)
22521 { # templates
22522 if(not defined $VirtualTable{1}{$ClassName})
22523 { # synchronize
22524 delete($VirtualTable{2}{$ClassName});
22525 }
22526 }
22527 }
22528 }
22529
22530 registerOverriding(1);
22531 registerOverriding(2);
22532
22533 setVirtFuncPositions(1);
22534 setVirtFuncPositions(2);
22535
22536 # Other
22537 addParamNames(1);
22538 addParamNames(2);
22539
22540 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022541}
22542
22543sub compareAPIs($)
22544{
22545 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022547 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022548 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022549
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022550 if($Level eq "Binary") {
22551 printMsg("INFO", "comparing ABIs ...");
22552 }
22553 else {
22554 printMsg("INFO", "comparing APIs ...");
22555 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022556
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022557 if($CheckHeadersOnly
22558 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022559 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022560 detectAdded_H($Level);
22561 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022562 }
22563 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022564 { # added/removed in libs
22565 detectAdded($Level);
22566 detectRemoved($Level);
22567 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022568
22569 mergeSymbols($Level);
22570 if(keys(%{$CheckedSymbols{$Level}})) {
22571 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022572 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022573
22574 $Cache{"mergeTypes"} = (); # free memory
22575
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022576 if($CheckHeadersOnly
22577 or $Level eq "Source")
22578 { # added/removed in headers
22579 mergeHeaders($Level);
22580 }
22581 else
22582 { # added/removed in libs
22583 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022584 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022585
22586 foreach my $S (keys(%{$CompatProblems{$Level}}))
22587 {
22588 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22589 {
22590 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22591 {
22592 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22593 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22594 }
22595 }
22596 }
22597 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022598}
22599
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022600sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022601{
22602 my %Opts = (
22603 "OStarget"=>$OStarget,
22604 "Debug"=>$Debug,
22605 "Quiet"=>$Quiet,
22606 "LogMode"=>$LogMode,
22607 "CheckHeadersOnly"=>$CheckHeadersOnly,
22608
22609 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022610 "GCC_PATH"=>$GCC_PATH,
22611 "TargetSysInfo"=>$TargetSysInfo,
22612 "CrossPrefix"=>$CrossPrefix,
22613 "TargetLibraryName"=>$TargetLibraryName,
22614 "CrossGcc"=>$CrossGcc,
22615 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022616 "NoStdInc"=>$NoStdInc,
22617
22618 "BinaryOnly" => $BinaryOnly,
22619 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022620 );
22621 return \%Opts;
22622}
22623
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022624sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022625{
22626 my %CODE_ERROR = reverse(%ERROR_CODE);
22627 return $CODE_ERROR{$_[0]};
22628}
22629
22630sub scenario()
22631{
22632 if($StdOut)
22633 { # enable quiet mode
22634 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022635 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022636 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022637 if(not $LogMode)
22638 { # default
22639 $LogMode = "w";
22640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022641 if($UserLang)
22642 { # --lang=C++
22643 $UserLang = uc($UserLang);
22644 $COMMON_LANGUAGE{1}=$UserLang;
22645 $COMMON_LANGUAGE{2}=$UserLang;
22646 }
22647 if($LoggingPath)
22648 {
22649 $OutputLogPath{1} = $LoggingPath;
22650 $OutputLogPath{2} = $LoggingPath;
22651 if($Quiet) {
22652 $COMMON_LOG_PATH = $LoggingPath;
22653 }
22654 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022655
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022656 if($Quick) {
22657 $ADD_TMPL_INSTANCES = 0;
22658 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022659 if($OutputDumpPath)
22660 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022661 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022662 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22663 }
22664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022665 if($BinaryOnly and $SourceOnly)
22666 { # both --binary and --source
22667 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022668 if(not $CmpSystems)
22669 {
22670 $BinaryOnly = 0;
22671 $SourceOnly = 0;
22672 }
22673
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022674 $DoubleReport = 1;
22675 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022676
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022677 if($OutputReportPath)
22678 { # --report-path
22679 $DoubleReport = 0;
22680 $JoinReport = 1;
22681 }
22682 }
22683 elsif($BinaryOnly or $SourceOnly)
22684 { # --binary or --source
22685 $DoubleReport = 0;
22686 $JoinReport = 0;
22687 }
22688 if($UseXML)
22689 { # --xml option
22690 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022691 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022693 if($ReportFormat)
22694 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022695 $ReportFormat = lc($ReportFormat);
22696 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022697 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022699 if($ReportFormat eq "htm")
22700 { # HTM == HTML
22701 $ReportFormat = "html";
22702 }
22703 elsif($ReportFormat eq "xml")
22704 { # --report-format=XML equal to --xml
22705 $UseXML = 1;
22706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022707 }
22708 else
22709 { # default: HTML
22710 $ReportFormat = "html";
22711 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022712 if($DumpFormat)
22713 { # validate
22714 $DumpFormat = lc($DumpFormat);
22715 if($DumpFormat!~/\A(xml|perl)\Z/) {
22716 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22717 }
22718 if($DumpFormat eq "xml")
22719 { # --dump-format=XML equal to --xml
22720 $UseXML = 1;
22721 }
22722 }
22723 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022724 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022725 $DumpFormat = "perl";
22726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022727 if($Quiet and $LogMode!~/a|n/)
22728 { # --quiet log
22729 if(-f $COMMON_LOG_PATH) {
22730 unlink($COMMON_LOG_PATH);
22731 }
22732 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022733 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022734 $CheckUndefined = 1;
22735 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022736 if($TestTool and $UseDumps)
22737 { # --test && --use-dumps == --test-dump
22738 $TestDump = 1;
22739 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022740 if($Tolerant)
22741 { # enable all
22742 $Tolerance = 1234;
22743 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022744 if($Help)
22745 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022746 HELP_MESSAGE();
22747 exit(0);
22748 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022749 if($InfoMsg)
22750 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022751 INFO_MESSAGE();
22752 exit(0);
22753 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022754 if($ShowVersion)
22755 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022756 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 +040022757 exit(0);
22758 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022759 if($DumpVersion)
22760 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022761 printMsg("INFO", $TOOL_VERSION);
22762 exit(0);
22763 }
22764 if($ExtendedCheck) {
22765 $CheckHeadersOnly = 1;
22766 }
22767 if($SystemRoot_Opt)
22768 { # user defined root
22769 if(not -e $SystemRoot_Opt) {
22770 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22771 }
22772 $SystemRoot = $SystemRoot_Opt;
22773 $SystemRoot=~s/[\/]+\Z//g;
22774 if($SystemRoot) {
22775 $SystemRoot = get_abs_path($SystemRoot);
22776 }
22777 }
22778 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022779
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022780 if($SortDump)
22781 {
22782 $Data::Dumper::Useperl = 1;
22783 $Data::Dumper::Sortkeys = \&dump_sorting;
22784 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022785
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022786 if($TargetLibsPath)
22787 {
22788 if(not -f $TargetLibsPath) {
22789 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22790 }
22791 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22792 $TargetLibs{$Lib} = 1;
22793 }
22794 }
22795 if($TargetHeadersPath)
22796 { # --headers-list
22797 if(not -f $TargetHeadersPath) {
22798 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22799 }
22800 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22801 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022802 $TargetHeaders{1}{get_filename($Header)} = 1;
22803 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022804 }
22805 }
22806 if($TargetHeader)
22807 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022808 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22809 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022810 }
22811 if($TestTool
22812 or $TestDump)
22813 { # --test, --test-dump
22814 detect_default_paths("bin|gcc"); # to compile libs
22815 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022816 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022817 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022818 exit(0);
22819 }
22820 if($DumpSystem)
22821 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022822
22823 if(not $TargetSysInfo) {
22824 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22825 }
22826
22827 if(not -d $TargetSysInfo) {
22828 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22829 }
22830
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022831 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022832 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022833 { # system XML descriptor
22834 if(not -f $DumpSystem) {
22835 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22836 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022837
22838 my $SDesc = readFile($DumpSystem);
22839 if(my $RelDir = $RelativeDirectory{1}) {
22840 $SDesc =~ s/{RELPATH}/$RelDir/g;
22841 }
22842
22843 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022844 foreach (@{$Ret->{"Tools"}})
22845 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022846 push_U($SystemPaths{"bin"}, $_);
22847 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022848 }
22849 if($Ret->{"CrossPrefix"}) {
22850 $CrossPrefix = $Ret->{"CrossPrefix"};
22851 }
22852 }
22853 elsif($SystemRoot_Opt)
22854 { # -sysroot "/" option
22855 # default target: /usr/lib, /usr/include
22856 # search libs: /usr/lib and /lib
22857 if(not -e $SystemRoot."/usr/lib") {
22858 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22859 }
22860 if(not -e $SystemRoot."/lib") {
22861 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22862 }
22863 if(not -e $SystemRoot."/usr/include") {
22864 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22865 }
22866 readSystemDescriptor("
22867 <name>
22868 $DumpSystem
22869 </name>
22870 <headers>
22871 $SystemRoot/usr/include
22872 </headers>
22873 <libs>
22874 $SystemRoot/usr/lib
22875 </libs>
22876 <search_libs>
22877 $SystemRoot/lib
22878 </search_libs>");
22879 }
22880 else {
22881 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22882 }
22883 detect_default_paths("bin|gcc"); # to check symbols
22884 if($OStarget eq "windows")
22885 { # to run dumpbin.exe
22886 # and undname.exe
22887 check_win32_env();
22888 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022889 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022890 exit(0);
22891 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022892
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022893 if($CmpSystems)
22894 { # --cmp-systems
22895 detect_default_paths("bin"); # to extract dumps
22896 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022897 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022898 exit(0);
22899 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022900
22901 if(not $CountSymbols)
22902 {
22903 if(not $TargetLibraryName) {
22904 exitStatus("Error", "library name is not selected (-l option)");
22905 }
22906 else
22907 { # validate library name
22908 if($TargetLibraryName=~/[\*\/\\]/) {
22909 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022911 }
22912 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022913
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022914 if(not $TargetTitle) {
22915 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022916 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022917
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022918 if($SymbolsListPath)
22919 {
22920 if(not -f $SymbolsListPath) {
22921 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22922 }
22923 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22924 $SymbolsList{$Interface} = 1;
22925 }
22926 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022927 if($TypesListPath)
22928 {
22929 if(not -f $TypesListPath) {
22930 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22931 }
22932 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22933 $TypesList{$Type} = 1;
22934 }
22935 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022936 if($SkipSymbolsListPath)
22937 {
22938 if(not -f $SkipSymbolsListPath) {
22939 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22940 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022941 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22942 {
22943 $SkipSymbols{1}{$Interface} = 1;
22944 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022945 }
22946 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022947 if($SkipTypesListPath)
22948 {
22949 if(not -f $SkipTypesListPath) {
22950 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22951 }
22952 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22953 {
22954 $SkipTypes{1}{$Type} = 1;
22955 $SkipTypes{2}{$Type} = 1;
22956 }
22957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022958 if($SkipHeadersPath)
22959 {
22960 if(not -f $SkipHeadersPath) {
22961 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22962 }
22963 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022964 { # register for both versions
22965 $SkipHeadersList{1}{$Path} = 1;
22966 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030022967
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022968 my ($CPath, $Type) = classifyPath($Path);
22969 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022970 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022971 }
22972 }
22973 if($ParamNamesPath)
22974 {
22975 if(not -f $ParamNamesPath) {
22976 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22977 }
22978 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22979 {
22980 if($Line=~s/\A(\w+)\;//)
22981 {
22982 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022983 if($Line=~/;(\d+);/)
22984 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022985 while($Line=~s/(\d+);(\w+)//) {
22986 $AddIntParams{$Interface}{$1}=$2;
22987 }
22988 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022989 else
22990 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022991 my $Num = 0;
22992 foreach my $Name (split(/;/, $Line)) {
22993 $AddIntParams{$Interface}{$Num++}=$Name;
22994 }
22995 }
22996 }
22997 }
22998 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023000 if($AppPath)
23001 {
23002 if(not -f $AppPath) {
23003 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23004 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023005
23006 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023007 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023008 $SymbolsList_App{$Interface} = 1;
23009 }
23010 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023011
23012 if($CountSymbols)
23013 {
23014 if(not -e $CountSymbols) {
23015 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23016 }
23017
23018 read_ABI_Dump(1, $CountSymbols);
23019
23020 foreach my $Id (keys(%{$SymbolInfo{1}}))
23021 {
23022 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23023 if(not $MnglName) {
23024 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23025 }
23026
23027 if(my $SV = $SymVer{1}{$MnglName}) {
23028 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23029 }
23030 else {
23031 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23032 }
23033
23034 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23035 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23036 }
23037 }
23038
23039 my $Count = 0;
23040 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23041 {
23042 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23043 next;
23044 }
23045 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23046 next;
23047 }
23048 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23049 next;
23050 }
23051
23052 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23053 }
23054
23055 printMsg("INFO", $Count);
23056 exit(0);
23057 }
23058
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023059 if($DumpAPI)
23060 { # --dump-abi
23061 # make an API dump
23062 create_ABI_Dump();
23063 exit($COMPILE_ERRORS);
23064 }
23065 # default: compare APIs
23066 # -d1 <path>
23067 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023068 compareInit();
23069 if($JoinReport or $DoubleReport)
23070 {
23071 compareAPIs("Binary");
23072 compareAPIs("Source");
23073 }
23074 elsif($BinaryOnly) {
23075 compareAPIs("Binary");
23076 }
23077 elsif($SourceOnly) {
23078 compareAPIs("Source");
23079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023080 exitReport();
23081}
23082
23083scenario();