blob: 247deeb21c239554f136527dd2afa81d6f584684 [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 Ponomarenko0f946a42016-07-02 19:10:59 +030094$TypesListPath, $SkipTypesListPath, $CheckPrivateABI, $CountSymbols, $OldStyle);
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 Ponomarenko0f946a42016-07-02 19:10:59 +0300225 "old-style!" => \$OldStyle,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400226# other options
227 "test!" => \$TestTool,
228 "test-dump!" => \$TestDump,
229 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400230 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400231 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400232 "p|params=s" => \$ParamNamesPath,
233 "relpath1|relpath=s" => \$RelativeDirectory{1},
234 "relpath2=s" => \$RelativeDirectory{2},
235 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400236 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400237 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400238 "bin-report-path=s" => \$BinaryReportPath,
239 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "log-path=s" => \$LoggingPath,
241 "log1-path=s" => \$OutputLogPath{1},
242 "log2-path=s" => \$OutputLogPath{2},
243 "logging-mode=s" => \$LogMode,
244 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300245 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400246 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400247 "extra-info=s" => \$ExtraInfo,
248 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400249 "force!" => \$Force,
250 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400251 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400252 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400253 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400254 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300255 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
256 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300257 "check-private-abi!" => \$CheckPrivateABI
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400258) or ERR_MESSAGE();
259
260sub ERR_MESSAGE()
261{
262 printMsg("INFO", "\n".$ShortUsage);
263 exit($ERROR_CODE{"Error"});
264}
265
266my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
267my $SLIB_TYPE = $LIB_TYPE;
268if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
269{ # show as "shared" library
270 $SLIB_TYPE = "shared";
271}
272my $LIB_EXT = getLIB_EXT($OSgroup);
273my $AR_EXT = getAR_EXT($OSgroup);
274my $BYTE_SIZE = 8;
275my $COMMON_LOG_PATH = "logs/run.log";
276
277my $HelpMessage="
278NAME:
279 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400280 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400281
282DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400283 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400284 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
285 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
286 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
287 and/or source-level compatibility: changes in calling stack, v-table changes,
288 removed symbols, renamed fields, etc. Binary incompatibility may result in
289 crashing or incorrect behavior of applications built with an old version of
290 a library if they run on a new one. Source incompatibility may result in
291 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400292
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400293 The tool is intended for developers of software libraries and maintainers
294 of operating systems who are interested in ensuring backward compatibility,
295 i.e. allow old applications to run or to be recompiled with newer library
296 versions.
297
298 Also the tool can be used by ISVs for checking applications portability to
299 new library versions. Found issues can be taken into account when adapting
300 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400301
302 This tool is free software: you can redistribute it and/or modify it
303 under the terms of the GNU LGPL or GNU GPL.
304
305USAGE:
306 $CmdName [options]
307
308EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400309 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400310
311 OLD.xml and NEW.xml are XML-descriptors:
312
313 <version>
314 1.0
315 </version>
316
317 <headers>
318 /path1/to/header(s)/
319 /path2/to/header(s)/
320 ...
321 </headers>
322
323 <libs>
324 /path1/to/library(ies)/
325 /path2/to/library(ies)/
326 ...
327 </libs>
328
329INFORMATION OPTIONS:
330 -h|-help
331 Print this help.
332
333 -i|-info
334 Print complete info.
335
336 -v|-version
337 Print version information.
338
339 -dumpversion
340 Print the tool version ($TOOL_VERSION) and don't do anything else.
341
342GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400343 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400344 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400346 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400347 Descriptor of 1st (old) library version.
348 It may be one of the following:
349
350 1. XML-descriptor (VERSION.xml file):
351
352 <version>
353 1.0
354 </version>
355
356 <headers>
357 /path1/to/header(s)/
358 /path2/to/header(s)/
359 ...
360 </headers>
361
362 <libs>
363 /path1/to/library(ies)/
364 /path2/to/library(ies)/
365 ...
366 </libs>
367
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300368 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400369
370 2. ABI dump generated by -dump option
371 3. Directory with headers and/or $SLIB_TYPE libraries
372 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400373
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300374 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400375 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400376
377 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400378 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400379
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400380 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400381 Descriptor of 2nd (new) library version.
382
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400383 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400384 Create library ABI dump for the input XML descriptor. You can
385 transfer it anywhere and pass instead of the descriptor. Also
386 it can be used for debugging the tool.
387
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300388 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400389
390sub HELP_MESSAGE() {
391 printMsg("INFO", $HelpMessage."
392MORE INFO:
393 $CmdName --info\n");
394}
395
396sub INFO_MESSAGE()
397{
398 printMsg("INFO", "$HelpMessage
399EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400400 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300401 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402 for portability to the new library version.
403
404 -static-libs
405 Check static libraries instead of the shared ones. The <libs> section
406 of the XML-descriptor should point to static libraries location.
407
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300408 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400409 Path to the cross GCC compiler to use instead of the usual (host) GCC.
410
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300411 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400412 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300413
414 -gcc-options OPTS
415 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400417 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400418 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400419 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400420
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400421 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400422 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200423 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400424
425 In general case you should specify it in the XML-descriptor:
426 <version>
427 VERSION
428 </version>
429
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400430 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400431 Specify 2nd library version outside the descriptor.
432
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400433 -vnum NUM
434 Specify the library version in the generated ABI dump. The <version> section
435 of the input XML descriptor will be overwritten in this case.
436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437 -s|-strict
438 Treat all compatibility warnings as problems. Add a number of \"Low\"
439 severity problems to the return value of the tool.
440
441 -headers-only
442 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
443 provide a low quality compatibility report with false positives and
444 without detecting of added/removed symbols.
445
446 Alternatively you can write \"none\" word to the <libs> section
447 in the XML-descriptor:
448 <libs>
449 none
450 </libs>
451
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400452 -show-retval
453 Show the symbol's return type in the report.
454
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400455 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300456 This option allows to specify a file with a list of symbols (mangled
457 names in C++) that should be checked. Other symbols will not be checked.
458
459 -types-list PATH
460 This option allows to specify a file with a list of types that should
461 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400462
463 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300464 The list of symbols that should not be checked.
465
466 -skip-types PATH
467 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400468
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400469 -headers-list PATH
470 The file with a list of headers, that should be checked/dumped.
471
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400472 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400473 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400474
475 -header NAME
476 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400477
478 -use-dumps
479 Make dumps for two versions of a library and compare dumps. This should
480 increase the performance of the tool and decrease the system memory usage.
481
482 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400483 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400484
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400485 -dump-system NAME -sysroot DIR
486 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400487 create XML descriptors and make ABI dumps for each library. The result
488 set of ABI dumps can be compared (--cmp-systems) with the other one
489 created for other version of operating system in order to check them for
490 compatibility. Do not forget to specify -cross-gcc option if your target
491 system requires some specific version of GCC compiler (different from
492 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400493 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400494
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400495 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400496 The same as the previous option but takes an XML descriptor of the target
497 system as input, where you should describe it:
498
499 /* Primary sections */
500
501 <name>
502 /* Name of the system */
503 </name>
504
505 <headers>
506 /* The list of paths to header files and/or
507 directories with header files, one per line */
508 </headers>
509
510 <libs>
511 /* The list of paths to shared libraries and/or
512 directories with shared libraries, one per line */
513 </libs>
514
515 /* Optional sections */
516
517 <search_headers>
518 /* List of directories to be searched
519 for header files to automatically
520 generate include paths, one per line */
521 </search_headers>
522
523 <search_libs>
524 /* List of directories to be searched
525 for shared libraries to resolve
526 dependencies, one per line */
527 </search_libs>
528
529 <tools>
530 /* List of directories with tools used
531 for analysis (GCC toolchain), one per line */
532 </tools>
533
534 <cross_prefix>
535 /* GCC toolchain prefix.
536 Examples:
537 arm-linux-gnueabi
538 arm-none-symbianelf */
539 </cross_prefix>
540
541 <gcc_options>
542 /* Additional GCC options, one per line */
543 </gcc_options>
544
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400545 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300546 This option should be used with -dump-system option to dump
547 ABI of operating systems and configure the dumping process.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400548
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400549 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400550 Compare two system ABI dumps. Create compatibility reports for each
551 library and the common HTML report including the summary of test
552 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400553 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400554
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400555 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400556 The file with a list of libraries, that should be dumped by
557 the -dump-system option or should be checked by the -cmp-systems option.
558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400559 -ext|-extended
560 If your library A is supposed to be used by other library B and you
561 want to control the ABI of B, then you should enable this option. The
562 tool will check for changes in all data types, even if they are not
563 used by any function in the library A. Such data types are not part
564 of the A library ABI, but may be a part of the ABI of the B library.
565
566 The short scheme is:
567 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
568
569 -q|-quiet
570 Print all messages to the file instead of stdout and stderr.
571 Default path (can be changed by -log-path option):
572 $COMMON_LOG_PATH
573
574 -stdout
575 Print analysis results (compatibility reports and ABI dumps) to stdout
576 instead of creating a file. This would allow piping data to other programs.
577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400579 Change format of compatibility report.
580 Formats:
581 htm - HTML format (default)
582 xml - XML format
583
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400584 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400585 Change format of ABI dump.
586 Formats:
587 perl - Data::Dumper format (default)
588 xml - XML format
589
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400590 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400591 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400592
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400593 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400594 Set library language (C or C++). You can use this option if the tool
595 cannot auto-detect a language. This option may be useful for checking
596 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400597
598 -arch ARCH
599 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
600 ect.). The option is useful if the tool cannot detect correct architecture
601 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400602
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400603 -binary|-bin|-abi
604 Show \"Binary\" compatibility problems only.
605 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400606 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400607
608 -source|-src|-api
609 Show \"Source\" compatibility problems only.
610 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400611 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400612
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400613 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400614 The maximum number of affected symbols listed under the description
615 of the changed type in the report.
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +0300616
617 -count-symbols PATH
618 Count total public symbols in the ABI dump.
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +0300619
620 -old-style
621 Generate old-style report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400623OTHER OPTIONS:
624 -test
625 Run internal tests. Create two binary incompatible versions of a sample
626 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300627 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400628
629 -test-dump
630 Test ability to create, read and compare ABI dumps.
631
632 -debug
633 Debugging mode. Print debug info on the screen. Save intermediate
634 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400636
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400637 Also consider using --dump option for debugging the tool.
638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400639 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400640 If your header files are written in C language and can be compiled
641 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
642 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400643
644 -cpp-incompatible
645 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400646
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400647 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400648 Path to file with the function parameter names. It can be used
649 for improving report view if the library header files have no
650 parameter names. File format:
651
652 func1;param1;param2;param3 ...
653 func2;param1;param2;param3 ...
654 ...
655
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400656 -relpath PATH
657 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400658 for dumping the library ABI (see -dump option).
659
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 -relpath1 PATH
661 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400663 -relpath2 PATH
664 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400665
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400666 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400667 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400668 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400669 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400670
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400671 -sort
672 Enable sorting of data in ABI dumps.
673
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400675 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400676 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400678
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400679 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400680 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400682 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400685 Path to \"Source\" compatibility report.
686 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400687 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400688
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400690 Log path for all messages.
691 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695 Log path for 1st version of a library.
696 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400698
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400700 Log path for 2nd version of a library.
701 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400702 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400703
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400705 Change logging mode.
706 Modes:
707 w - overwrite old logs (default)
708 a - append old logs
709 n - do not write any logs
710
711 -list-affected
712 Generate file with the list of incompatible
713 symbols beside the HTML compatibility report.
714 Use 'c++filt \@file' command from GNU binutils
715 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400716 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400718 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 The component name in the title and summary of the HTML report.
722 Default:
723 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300724
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300725 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400726 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400727 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728
729 -extra-info DIR
730 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400731
732 -extra-dump
733 Create extended ABI dump containing all symbols
734 from the translation unit.
735
736 -force
737 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400738
739 -tolerance LEVEL
740 Apply a set of heuristics to successfully compile input
741 header files. You can enable several tolerance levels by
742 joining them into one string (e.g. 13, 124, etc.).
743 Levels:
744 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
745 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
Sangwoo Lee159324e2016-06-26 01:55:55 +0900746 3 - skip headers that include non-Linux headers
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400747 4 - skip headers included by others
748
749 -tolerant
750 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400751
752 -check
753 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400754
755 -quick
756 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400757
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300758 -skip-internal-symbols PATTERN
759 Do not check symbols matched by the pattern.
760
761 -skip-internal-types PATTERN
762 Do not check types matched by the pattern.
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +0300763
764 -check-private-abi
765 Check data types from the private part of the ABI when
766 comparing ABI dumps created by the ABI Dumper tool with
767 use of the -public-headers option.
768
769 Requires ABI Dumper >= 0.99.14
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400770
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400771REPORT:
772 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400773 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400774
775 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400776 logs/LIB_NAME/V1/log.txt
777 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400778
779EXIT CODES:
780 0 - Compatible. The tool has run without any errors.
781 non-zero - Incompatible or the tool has run with errors.
782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400783MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300784 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400785}
786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400787my %Operator_Indication = (
788 "not" => "~",
789 "assign" => "=",
790 "andassign" => "&=",
791 "orassign" => "|=",
792 "xorassign" => "^=",
793 "or" => "|",
794 "xor" => "^",
795 "addr" => "&",
796 "and" => "&",
797 "lnot" => "!",
798 "eq" => "==",
799 "ne" => "!=",
800 "lt" => "<",
801 "lshift" => "<<",
802 "lshiftassign" => "<<=",
803 "rshiftassign" => ">>=",
804 "call" => "()",
805 "mod" => "%",
806 "modassign" => "%=",
807 "subs" => "[]",
808 "land" => "&&",
809 "lor" => "||",
810 "rshift" => ">>",
811 "ref" => "->",
812 "le" => "<=",
813 "deref" => "*",
814 "mult" => "*",
815 "preinc" => "++",
816 "delete" => " delete",
817 "vecnew" => " new[]",
818 "vecdelete" => " delete[]",
819 "predec" => "--",
820 "postinc" => "++",
821 "postdec" => "--",
822 "plusassign" => "+=",
823 "plus" => "+",
824 "minus" => "-",
825 "minusassign" => "-=",
826 "gt" => ">",
827 "ge" => ">=",
828 "new" => " new",
829 "multassign" => "*=",
830 "divassign" => "/=",
831 "div" => "/",
832 "neg" => "-",
833 "pos" => "+",
834 "memref" => "->*",
835 "compound" => "," );
836
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400837my %UnknownOperator;
838
839my %NodeType= (
840 "array_type" => "Array",
841 "binfo" => "Other",
842 "boolean_type" => "Intrinsic",
843 "complex_type" => "Intrinsic",
844 "const_decl" => "Other",
845 "enumeral_type" => "Enum",
846 "field_decl" => "Other",
847 "function_decl" => "Other",
848 "function_type" => "FunctionType",
849 "identifier_node" => "Other",
850 "integer_cst" => "Other",
851 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400852 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400853 "method_type" => "MethodType",
854 "namespace_decl" => "Other",
855 "parm_decl" => "Other",
856 "pointer_type" => "Pointer",
857 "real_cst" => "Other",
858 "real_type" => "Intrinsic",
859 "record_type" => "Struct",
860 "reference_type" => "Ref",
861 "string_cst" => "Other",
862 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400863 "template_type_parm" => "TemplateParam",
864 "typename_type" => "TypeName",
865 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400866 "tree_list" => "Other",
867 "tree_vec" => "Other",
868 "type_decl" => "Other",
869 "union_type" => "Union",
870 "var_decl" => "Other",
871 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400872 "nop_expr" => "Other", #
873 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400874 "offset_type" => "Other" );
875
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400876my %CppKeywords_C = map {$_=>1} (
877 # C++ 2003 keywords
878 "public",
879 "protected",
880 "private",
881 "default",
882 "template",
883 "new",
884 #"asm",
885 "dynamic_cast",
886 "auto",
887 "try",
888 "namespace",
889 "typename",
890 "using",
891 "reinterpret_cast",
892 "friend",
893 "class",
894 "virtual",
895 "const_cast",
896 "mutable",
897 "static_cast",
898 "export",
899 # C++0x keywords
900 "noexcept",
901 "nullptr",
902 "constexpr",
903 "static_assert",
904 "explicit",
905 # cannot be used as a macro name
906 # as it is an operator in C++
907 "and",
908 #"and_eq",
909 "not",
910 #"not_eq",
911 "or"
912 #"or_eq",
913 #"bitand",
914 #"bitor",
915 #"xor",
916 #"xor_eq",
917 #"compl"
918);
919
920my %CppKeywords_F = map {$_=>1} (
921 "delete",
922 "catch",
923 "alignof",
924 "thread_local",
925 "decltype",
926 "typeid"
927);
928
929my %CppKeywords_O = map {$_=>1} (
930 "bool",
931 "register",
932 "inline",
933 "operator"
934);
935
936my %CppKeywords_A = map {$_=>1} (
937 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400938 "throw",
939 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400940);
941
942foreach (keys(%CppKeywords_C),
943keys(%CppKeywords_F),
944keys(%CppKeywords_O)) {
945 $CppKeywords_A{$_}=1;
946}
947
948# Header file extensions as described by gcc
949my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
950
951my %IntrinsicMangling = (
952 "void" => "v",
953 "bool" => "b",
954 "wchar_t" => "w",
955 "char" => "c",
956 "signed char" => "a",
957 "unsigned char" => "h",
958 "short" => "s",
959 "unsigned short" => "t",
960 "int" => "i",
961 "unsigned int" => "j",
962 "long" => "l",
963 "unsigned long" => "m",
964 "long long" => "x",
965 "__int64" => "x",
966 "unsigned long long" => "y",
967 "__int128" => "n",
968 "unsigned __int128" => "o",
969 "float" => "f",
970 "double" => "d",
971 "long double" => "e",
972 "__float80" => "e",
973 "__float128" => "g",
974 "..." => "z"
975);
976
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400977my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
978
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400979my %StdcxxMangling = (
980 "3std"=>"St",
981 "3std9allocator"=>"Sa",
982 "3std12basic_string"=>"Sb",
983 "3std12basic_stringIcE"=>"Ss",
984 "3std13basic_istreamIcE"=>"Si",
985 "3std13basic_ostreamIcE"=>"So",
986 "3std14basic_iostreamIcE"=>"Sd"
987);
988
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400989my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400990my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
991
992my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400993my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400995my %ConstantSuffix = (
996 "unsigned int"=>"u",
997 "long"=>"l",
998 "unsigned long"=>"ul",
999 "long long"=>"ll",
1000 "unsigned long long"=>"ull"
1001);
1002
1003my %ConstantSuffixR =
1004reverse(%ConstantSuffix);
1005
1006my %OperatorMangling = (
1007 "~" => "co",
1008 "=" => "aS",
1009 "|" => "or",
1010 "^" => "eo",
1011 "&" => "an",#ad (addr)
1012 "==" => "eq",
1013 "!" => "nt",
1014 "!=" => "ne",
1015 "<" => "lt",
1016 "<=" => "le",
1017 "<<" => "ls",
1018 "<<=" => "lS",
1019 ">" => "gt",
1020 ">=" => "ge",
1021 ">>" => "rs",
1022 ">>=" => "rS",
1023 "()" => "cl",
1024 "%" => "rm",
1025 "[]" => "ix",
1026 "&&" => "aa",
1027 "||" => "oo",
1028 "*" => "ml",#de (deref)
1029 "++" => "pp",#
1030 "--" => "mm",#
1031 "new" => "nw",
1032 "delete" => "dl",
1033 "new[]" => "na",
1034 "delete[]" => "da",
1035 "+=" => "pL",
1036 "+" => "pl",#ps (pos)
1037 "-" => "mi",#ng (neg)
1038 "-=" => "mI",
1039 "*=" => "mL",
1040 "/=" => "dV",
1041 "&=" => "aN",
1042 "|=" => "oR",
1043 "%=" => "rM",
1044 "^=" => "eO",
1045 "/" => "dv",
1046 "->*" => "pm",
1047 "->" => "pt",#rf (ref)
1048 "," => "cm",
1049 "?" => "qu",
1050 "." => "dt",
1051 "sizeof"=> "sz"#st
1052);
1053
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001054my %Intrinsic_Keywords = map {$_=>1} (
1055 "true",
1056 "false",
1057 "_Bool",
1058 "_Complex",
1059 "const",
1060 "int",
1061 "long",
1062 "void",
1063 "short",
1064 "float",
1065 "volatile",
1066 "restrict",
1067 "unsigned",
1068 "signed",
1069 "char",
1070 "double",
1071 "class",
1072 "struct",
1073 "union",
1074 "enum"
1075);
1076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001077my %GlibcHeader = map {$_=>1} (
1078 "aliases.h",
1079 "argp.h",
1080 "argz.h",
1081 "assert.h",
1082 "cpio.h",
1083 "ctype.h",
1084 "dirent.h",
1085 "envz.h",
1086 "errno.h",
1087 "error.h",
1088 "execinfo.h",
1089 "fcntl.h",
1090 "fstab.h",
1091 "ftw.h",
1092 "glob.h",
1093 "grp.h",
1094 "iconv.h",
1095 "ifaddrs.h",
1096 "inttypes.h",
1097 "langinfo.h",
1098 "limits.h",
1099 "link.h",
1100 "locale.h",
1101 "malloc.h",
1102 "math.h",
1103 "mntent.h",
1104 "monetary.h",
1105 "nl_types.h",
1106 "obstack.h",
1107 "printf.h",
1108 "pwd.h",
1109 "regex.h",
1110 "sched.h",
1111 "search.h",
1112 "setjmp.h",
1113 "shadow.h",
1114 "signal.h",
1115 "spawn.h",
1116 "stdarg.h",
1117 "stdint.h",
1118 "stdio.h",
1119 "stdlib.h",
1120 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001121 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001122 "tar.h",
1123 "termios.h",
1124 "time.h",
1125 "ulimit.h",
1126 "unistd.h",
1127 "utime.h",
1128 "wchar.h",
1129 "wctype.h",
1130 "wordexp.h" );
1131
1132my %GlibcDir = map {$_=>1} (
1133 "arpa",
1134 "bits",
1135 "gnu",
1136 "netinet",
1137 "net",
1138 "nfs",
1139 "rpc",
1140 "sys",
1141 "linux" );
1142
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001143my %WinHeaders = map {$_=>1} (
1144 "dos.h",
1145 "process.h",
1146 "winsock.h",
1147 "config-win.h",
1148 "mem.h",
1149 "windows.h",
1150 "winsock2.h",
1151 "crtdbg.h",
1152 "ws2tcpip.h"
1153);
1154
1155my %ObsoleteHeaders = map {$_=>1} (
1156 "iostream.h",
1157 "fstream.h"
1158);
1159
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001160my %AlienHeaders = map {$_=>1} (
1161 # Solaris
1162 "thread.h",
1163 "sys/atomic.h",
1164 # HPUX
1165 "sys/stream.h",
1166 # Symbian
1167 "AknDoc.h",
1168 # Atari ST
1169 "ext.h",
1170 "tos.h",
1171 # MS-DOS
1172 "alloc.h",
1173 # Sparc
1174 "sys/atomic.h"
1175);
1176
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001177my %ConfHeaders = map {$_=>1} (
1178 "atomic",
1179 "conf.h",
1180 "config.h",
1181 "configure.h",
1182 "build.h",
1183 "setup.h"
1184);
1185
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001186my %LocalIncludes = map {$_=>1} (
1187 "/usr/local/include",
1188 "/usr/local" );
1189
1190my %OS_AddPath=(
1191# These paths are needed if the tool cannot detect them automatically
1192 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001193 "include"=>[
1194 "/Library",
1195 "/Developer/usr/include"
1196 ],
1197 "lib"=>[
1198 "/Library",
1199 "/Developer/usr/lib"
1200 ],
1201 "bin"=>[
1202 "/Developer/usr/bin"
1203 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001204 },
1205 "beos"=>{
1206 # Haiku has GCC 2.95.3 by default
1207 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001208 "include"=>[
1209 "/boot/common",
1210 "/boot/develop"
1211 ],
1212 "lib"=>[
1213 "/boot/common/lib",
1214 "/boot/system/lib",
1215 "/boot/apps"
1216 ],
1217 "bin"=>[
1218 "/boot/common/bin",
1219 "/boot/system/bin",
1220 "/boot/develop/abi"
1221 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001223);
1224
1225my %Slash_Type=(
1226 "default"=>"/",
1227 "windows"=>"\\"
1228);
1229
1230my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1231
1232# Global Variables
1233my %COMMON_LANGUAGE=(
1234 1 => "C",
1235 2 => "C" );
1236
1237my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001238my $MAX_CPPFILT_FILE_SIZE = 50000;
1239my $CPPFILT_SUPPORT_FILE;
1240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001241my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001243my $STDCXX_TESTING = 0;
1244my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001245my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001246
1247my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001248my $CheckUndefined = 0;
1249
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001250my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001251if($TargetComponent_Opt) {
1252 $TargetComponent = lc($TargetComponent_Opt);
1253}
1254else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001255{ # default: library
1256 # other components: header, system, ...
1257 $TargetComponent = "library";
1258}
1259
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001260my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001261
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001262my $SystemRoot;
1263
1264my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001265my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001266my %LOG_PATH;
1267my %DEBUG_PATH;
1268my %Cache;
1269my %LibInfo;
1270my $COMPILE_ERRORS = 0;
1271my %CompilerOptions;
1272my %CheckedDyLib;
1273my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1274
1275# Constants (#defines)
1276my %Constants;
1277my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001278my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001279
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001280# Extra Info
1281my %SymbolHeader;
1282my %KnownLibs;
1283
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001284# Templates
1285my %TemplateInstance;
1286my %BasicTemplate;
1287my %TemplateArg;
1288my %TemplateDecl;
1289my %TemplateMap;
1290
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001291# Types
1292my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001293my %SkipTypes = (
1294 "1"=>{},
1295 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001296my %CheckedTypes;
1297my %TName_Tid;
1298my %EnumMembName_Id;
1299my %NestedNameSpaces = (
1300 "1"=>{},
1301 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001302my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001303my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001304my %ClassVTable;
1305my %ClassVTable_Content;
1306my %VTableClass;
1307my %AllocableClass;
1308my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001309my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001310my %Class_SubClasses;
1311my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001312my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001313my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001314
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001315my %CheckedTypeInfo;
1316
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001317# Typedefs
1318my %Typedef_BaseName;
1319my %Typedef_Tr;
1320my %Typedef_Eq;
1321my %StdCxxTypedef;
1322my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001323my %MissedBase;
1324my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001325my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001326
1327# Symbols
1328my %SymbolInfo;
1329my %tr_name;
1330my %mangled_name_gcc;
1331my %mangled_name;
1332my %SkipSymbols = (
1333 "1"=>{},
1334 "2"=>{} );
1335my %SkipNameSpaces = (
1336 "1"=>{},
1337 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001338my %AddNameSpaces = (
1339 "1"=>{},
1340 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001341my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001342my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001343my %SymbolsList_App;
1344my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001345my %Symbol_Library = (
1346 "1"=>{},
1347 "2"=>{} );
1348my %Library_Symbol = (
1349 "1"=>{},
1350 "2"=>{} );
1351my %DepSymbol_Library = (
1352 "1"=>{},
1353 "2"=>{} );
1354my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355 "1"=>{},
1356 "2"=>{} );
1357my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001358my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001359my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001360my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001361my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001362my %Library_Needed= (
1363 "1"=>{},
1364 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001365
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001366# Extra Info
1367my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001368my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001369
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001370# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001371my %Include_Preamble = (
1372 "1"=>[],
1373 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001375my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001376my %HeaderName_Paths;
1377my %Header_Dependency;
1378my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001379my %Include_Paths = (
1380 "1"=>[],
1381 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001382my %INC_PATH_AUTODETECT = (
1383 "1"=>1,
1384 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001385my %Add_Include_Paths = (
1386 "1"=>[],
1387 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001388my %Skip_Include_Paths;
1389my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001390my %Header_ErrorRedirect;
1391my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001392my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001393my %Header_ShouldNotBeUsed;
1394my %RecursiveIncludes;
1395my %Header_Include_Prefix;
1396my %SkipHeaders;
1397my %SkipHeadersList=(
1398 "1"=>{},
1399 "2"=>{} );
1400my %SkipLibs;
1401my %Include_Order;
1402my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001403my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001404my %TUnit_Funcs;
1405my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001406
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001407my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001408 "1"=>0,
1409 "2"=>0 );
1410my %AutoPreambleMode = (
1411 "1"=>0,
1412 "2"=>0 );
1413my %MinGWMode = (
1414 "1"=>0,
1415 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001416my %Cpp0xMode = (
1417 "1"=>0,
1418 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001419
1420# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001421my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001422my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001423my %RegisteredSONAMEs;
1424my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001425
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001426my %CheckedArch;
1427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428# System Objects
1429my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001430my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001431my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001432
1433# System Headers
1434my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001435my @DefaultCppPaths;
1436my @DefaultGccPaths;
1437my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438my %DefaultCppHeader;
1439my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001440my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001441
1442# Merging
1443my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001444my $Version;
1445my %AddedInt;
1446my %RemovedInt;
1447my %AddedInt_Virt;
1448my %RemovedInt_Virt;
1449my %VirtualReplacement;
1450my %ChangedTypedef;
1451my %CompatRules;
1452my %IncompleteRules;
1453my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001454my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001455my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001456my %ReturnedClass;
1457my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001458my %SourceAlternative;
1459my %SourceAlternative_B;
1460my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001461my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001462
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03001463#Report
1464my %TypeChanges;
1465
1466#Speedup
1467my %TypeProblemsIndex;
1468
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001469# Calling Conventions
1470my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001471 1=>{ "R"=>0, "P"=>0 },
1472 2=>{ "R"=>0, "P"=>0 }
1473);
1474
1475# ABI Dump
1476my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001477
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001478# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001479my %TargetLibs;
1480my %TargetHeaders;
1481
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001482# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001483my $OStarget = $OSgroup;
1484my %TargetTools;
1485
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001486# Recursion locks
1487my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001488my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001489my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001490my @RecurInclude;
1491my @RecurConstant;
1492
1493# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001494my %SystemPaths = (
1495 "include"=>[],
1496 "lib"=>[],
1497 "bin"=>[]
1498);
1499my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001500my $GCC_PATH;
1501
1502# Symbols versioning
1503my %SymVer = (
1504 "1"=>{},
1505 "2"=>{} );
1506
1507# Problem descriptions
1508my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001509my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001510my %TotalAffected;
1511
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001512# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001513my $ContentID = 1;
1514my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +03001515my $ContentSpanStart_Affected = "<span class=\"sect_aff\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1516my $ContentSpanStart_Info = "<span class=\"sect_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001517my $ContentSpanEnd = "</span>\n";
1518my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1519my $ContentDivEnd = "</div>\n";
1520my $Content_Counter = 0;
1521
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001522# Modes
1523my $JoinReport = 1;
1524my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001526my %Severity_Val=(
1527 "High"=>3,
1528 "Medium"=>2,
1529 "Low"=>1,
1530 "Safe"=>-1
1531);
1532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001533sub get_Modules()
1534{
1535 my $TOOL_DIR = get_dirname($0);
1536 if(not $TOOL_DIR)
1537 { # patch for MS Windows
1538 $TOOL_DIR = ".";
1539 }
1540 my @SEARCH_DIRS = (
1541 # tool's directory
1542 abs_path($TOOL_DIR),
1543 # relative path to modules
1544 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001545 # install path
1546 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001547 );
1548 foreach my $DIR (@SEARCH_DIRS)
1549 {
1550 if(not is_abs($DIR))
1551 { # relative path
1552 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1553 }
1554 if(-d $DIR."/modules") {
1555 return $DIR."/modules";
1556 }
1557 }
1558 exitStatus("Module_Error", "can't find modules");
1559}
1560
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001561my %LoadedModules = ();
1562
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001563sub loadModule($)
1564{
1565 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001566 if(defined $LoadedModules{$Name}) {
1567 return;
1568 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001569 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1570 if(not -f $Path) {
1571 exitStatus("Module_Error", "can't access \'$Path\'");
1572 }
1573 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001574 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001575}
1576
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001577sub readModule($$)
1578{
1579 my ($Module, $Name) = @_;
1580 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1581 if(not -f $Path) {
1582 exitStatus("Module_Error", "can't access \'$Path\'");
1583 }
1584 return readFile($Path);
1585}
1586
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001587sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001588{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001589 my $Number = $_[0];
1590 if(not $Number) {
1591 $Number = 1;
1592 }
1593 else {
1594 $Number = int($Number)+1;
1595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001596 if($Number>3) {
1597 return $Number."th";
1598 }
1599 elsif($Number==1) {
1600 return "1st";
1601 }
1602 elsif($Number==2) {
1603 return "2nd";
1604 }
1605 elsif($Number==3) {
1606 return "3rd";
1607 }
1608 else {
1609 return $Number;
1610 }
1611}
1612
1613sub search_Tools($)
1614{
1615 my $Name = $_[0];
1616 return "" if(not $Name);
1617 if(my @Paths = keys(%TargetTools))
1618 {
1619 foreach my $Path (@Paths)
1620 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001621 if(-f join_P($Path, $Name)) {
1622 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001623 }
1624 if($CrossPrefix)
1625 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001626 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001627 if(-f $Candidate) {
1628 return $Candidate;
1629 }
1630 }
1631 }
1632 }
1633 else {
1634 return "";
1635 }
1636}
1637
1638sub synch_Cmd($)
1639{
1640 my $Name = $_[0];
1641 if(not $GCC_PATH)
1642 { # GCC was not found yet
1643 return "";
1644 }
1645 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001646 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001647 return $Candidate;
1648 }
1649 return "";
1650}
1651
1652sub get_CmdPath($)
1653{
1654 my $Name = $_[0];
1655 return "" if(not $Name);
1656 if(defined $Cache{"get_CmdPath"}{$Name}) {
1657 return $Cache{"get_CmdPath"}{$Name};
1658 }
1659 my %BinUtils = map {$_=>1} (
1660 "c++filt",
1661 "objdump",
1662 "readelf"
1663 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001664 if($BinUtils{$Name} and $GCC_PATH)
1665 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001666 if(my $Dir = get_dirname($GCC_PATH)) {
1667 $TargetTools{$Dir}=1;
1668 }
1669 }
1670 my $Path = search_Tools($Name);
1671 if(not $Path and $OSgroup eq "windows") {
1672 $Path = search_Tools($Name.".exe");
1673 }
1674 if(not $Path and $BinUtils{$Name})
1675 {
1676 if($CrossPrefix)
1677 { # user-defined prefix
1678 $Path = search_Cmd($CrossPrefix."-".$Name);
1679 }
1680 }
1681 if(not $Path and $BinUtils{$Name})
1682 {
1683 if(my $Candidate = synch_Cmd($Name))
1684 { # synch with GCC
1685 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001686 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001687 if(-f $Candidate) {
1688 $Path = $Candidate;
1689 }
1690 }
1691 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001692 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001693 $Path = $Candidate;
1694 }
1695 }
1696 }
1697 if(not $Path) {
1698 $Path = search_Cmd($Name);
1699 }
1700 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001701 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001702 $Path=search_Cmd($Name.".exe");
1703 }
1704 if($Path=~/\s/) {
1705 $Path = "\"".$Path."\"";
1706 }
1707 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1708}
1709
1710sub search_Cmd($)
1711{
1712 my $Name = $_[0];
1713 return "" if(not $Name);
1714 if(defined $Cache{"search_Cmd"}{$Name}) {
1715 return $Cache{"search_Cmd"}{$Name};
1716 }
1717 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1718 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1719 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001720 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001721 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001722 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001723 if(-f $CmdPath)
1724 {
1725 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001726 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001727 }
1728 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1729 }
1730 }
1731 return ($Cache{"search_Cmd"}{$Name} = "");
1732}
1733
1734sub get_CmdPath_Default($)
1735{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 return "" if(not $_[0]);
1737 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1738 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001739 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001740 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1741}
1742
1743sub get_CmdPath_Default_I($)
1744{ # search in PATH
1745 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001746 if($Name=~/find/)
1747 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001748 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001749 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001750 }
1751 }
1752 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001753 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001754 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001755 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001756 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001757 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001758 if($OSgroup eq "windows")
1759 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001760 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001761 return $Name;
1762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001763 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001764 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001765 {
1766 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001767 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001768 }
1769 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001770 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001771}
1772
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001773sub classifyPath($)
1774{
1775 my $Path = $_[0];
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001776 if($Path=~/[\*\+\(\[\|]/)
1777 { # pattern
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001778 return ($Path, "Pattern");
1779 }
1780 elsif($Path=~/[\/\\]/)
1781 { # directory or relative path
1782 return (path_format($Path, $OSgroup), "Path");
1783 }
1784 else {
1785 return ($Path, "Name");
1786 }
1787}
1788
1789sub readDescriptor($$)
1790{
1791 my ($LibVersion, $Content) = @_;
1792 return if(not $LibVersion);
1793 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1794 if(not $Content) {
1795 exitStatus("Error", "$DName is empty");
1796 }
1797 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001798 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001799 }
1800 $Content=~s/\/\*(.|\n)+?\*\///g;
1801 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001802
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1804 if($TargetVersion{$LibVersion}) {
1805 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1806 }
1807 if(not $Descriptor{$LibVersion}{"Version"}) {
1808 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1809 }
1810 if($Content=~/{RELPATH}/)
1811 {
1812 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1813 $Content =~ s/{RELPATH}/$RelDir/g;
1814 }
1815 else
1816 {
1817 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1818 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1819 }
1820 }
1821
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001822 my $DHeaders = parseTag(\$Content, "headers");
1823 if(not $DHeaders) {
1824 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1825 }
1826 elsif(lc($DHeaders) ne "none")
1827 { # append the descriptor headers list
1828 if($Descriptor{$LibVersion}{"Headers"})
1829 { # multiple descriptors
1830 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001831 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001832 else {
1833 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1834 }
1835 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1836 {
1837 if(not -e $Path) {
1838 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001839 }
1840 }
1841 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001842
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001843 if(not $CheckHeadersOnly_Opt)
1844 {
1845 my $DObjects = parseTag(\$Content, "libs");
1846 if(not $DObjects) {
1847 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1848 }
1849 elsif(lc($DObjects) ne "none")
1850 { # append the descriptor libraries list
1851 if($Descriptor{$LibVersion}{"Libs"})
1852 { # multiple descriptors
1853 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1854 }
1855 else {
1856 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1857 }
1858 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1859 {
1860 if(not -e $Path) {
1861 exitStatus("Access_Error", "can't access \'$Path\'");
1862 }
1863 }
1864 }
1865 }
1866 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1867 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001868 if(not -d $Path) {
1869 exitStatus("Access_Error", "can't access directory \'$Path\'");
1870 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001871 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001872 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001873 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001874 }
1875 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1876 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001877 if(not -d $Path) {
1878 exitStatus("Access_Error", "can't access directory \'$Path\'");
1879 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001880 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001881 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001882 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001883 }
1884 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1885 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001886 if(not -d $Path) {
1887 exitStatus("Access_Error", "can't access directory \'$Path\'");
1888 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001889 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001891 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001892 $TargetTools{$Path}=1;
1893 }
1894 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1895 $CrossPrefix = $Prefix;
1896 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001897 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1899 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001900 if(not -d $Path) {
1901 exitStatus("Access_Error", "can't access directory \'$Path\'");
1902 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001903 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001904 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001905 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001907 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001908 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1909 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001910 if(not -d $Path) {
1911 exitStatus("Access_Error", "can't access directory \'$Path\'");
1912 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001913 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001914 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001915 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
1917 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001918 { # skip some auto-generated include paths
1919 if(not is_abs($Path))
1920 {
1921 if(my $P = abs_path($Path)) {
1922 $Path = $P;
1923 }
1924 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001925 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 }
1927 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001928 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001929 my ($CPath, $Type) = classifyPath($Path);
1930 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001931 }
1932 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001933 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1934 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001935 if($Option!~/\A\-(Wl|l|L)/)
1936 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001937 $CompilerOptions{$LibVersion} .= " ".$Option;
1938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001939 }
1940 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1941 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1942 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001943 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +03001944
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001945 my ($CPath, $Type) = classifyPath($Path);
1946 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001947 }
1948 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1949 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1950 {
1951 my ($CPath, $Type) = classifyPath($Path);
1952 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1953 }
1954 if(my $DDefines = parseTag(\$Content, "defines"))
1955 {
1956 if($Descriptor{$LibVersion}{"Defines"})
1957 { # multiple descriptors
1958 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1959 }
1960 else {
1961 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1962 }
1963 }
1964 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1965 {
1966 if($Order=~/\A(.+):(.+)\Z/) {
1967 $Include_Order{$LibVersion}{$1} = $2;
1968 }
1969 }
1970 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1971 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001972 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001973 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1974 }
1975 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1976 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001977 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001978 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1979 }
1980 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1981 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1982 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001983 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1984 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001986 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1987 $SkipConstants{$LibVersion}{$Constant} = 1;
1988 }
1989 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1990 {
1991 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001992 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1994 }
1995 else {
1996 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1997 }
1998 }
1999}
2000
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002001sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002002{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002003 my $CodeRef = shift(@_);
2004 my $Tag = shift(@_);
2005 if(not $Tag or not $CodeRef) {
2006 return undef;
2007 }
2008 my $Sp = 0;
2009 if(@_) {
2010 $Sp = shift(@_);
2011 }
2012 my $Start = index(${$CodeRef}, "<$Tag>");
2013 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002014 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002015 my $End = index(${$CodeRef}, "</$Tag>");
2016 if($End!=-1)
2017 {
2018 my $TS = length($Tag)+3;
2019 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2020 substr($Content, 0, $TS-1, ""); # cut start tag
2021 substr($Content, -$TS, $TS, ""); # cut end tag
2022 if(not $Sp)
2023 {
2024 $Content=~s/\A\s+//g;
2025 $Content=~s/\s+\Z//g;
2026 }
2027 if(substr($Content, 0, 1) ne "<") {
2028 $Content = xmlSpecChars_R($Content);
2029 }
2030 return $Content;
2031 }
2032 }
2033 return undef;
2034}
2035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002036sub getInfo($)
2037{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002038 my $DumpPath = $_[0];
2039 return if(not $DumpPath or not -f $DumpPath);
2040
2041 readTUDump($DumpPath);
2042
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043 # processing info
2044 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002045
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002046 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002047 setAnonTypedef_All();
2048 }
2049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 getTypeInfo_All();
2051 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002052 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002053 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002054 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002055
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002056 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002057 %LibInfo = ();
2058 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002059 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002061 %TemplateDecl = ();
2062 %StdCxxTypedef = ();
2063 %MissedTypedef = ();
2064 %Typedef_Tr = ();
2065 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002066 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002067
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002068 # clean cache
2069 delete($Cache{"getTypeAttr"});
2070 delete($Cache{"getTypeDeclId"});
2071
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002072 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002073 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002074 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002075 }
2076 else
2077 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002078 if($BinaryOnly and not $ExtendedCheck)
2079 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002080 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002081 }
2082 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002083 remove_Unused($Version, "Extended");
2084 }
2085 }
2086
2087 if($CheckInfo)
2088 {
2089 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2090 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2091 }
2092
2093 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2094 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002095 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002096 }
2097
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002098 if($Debug) {
2099 # debugMangling($Version);
2100 }
2101}
2102
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002103sub readTUDump($)
2104{
2105 my $DumpPath = $_[0];
2106
2107 open(TU_DUMP, $DumpPath);
2108 local $/ = undef;
2109 my $Content = <TU_DUMP>;
2110 close(TU_DUMP);
2111
2112 unlink($DumpPath);
2113
2114 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002115 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002116
2117 # clean memory
2118 undef $Content;
2119
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002120 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002121
2122 foreach (0 .. $#Lines)
2123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002124 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002125 { # get a number and attributes of a node
2126 next if(not $NodeType{$2});
2127 $LibInfo{$Version}{"info_type"}{$1}=$2;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03002128 $LibInfo{$Version}{"info"}{$1}=$3." ";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002129 }
2130
2131 # clean memory
2132 delete($Lines[$_]);
2133 }
2134
2135 # clean memory
2136 undef @Lines;
2137}
2138
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002139sub simplifyConstants()
2140{
2141 foreach my $Constant (keys(%{$Constants{$Version}}))
2142 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002143 if(defined $Constants{$Version}{$Constant}{"Header"})
2144 {
2145 my $Value = $Constants{$Version}{$Constant}{"Value"};
2146 if(defined $EnumConstants{$Version}{$Value}) {
2147 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2148 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002149 }
2150 }
2151}
2152
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002153sub simplifyNames()
2154{
2155 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2156 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002157 if($Typedef_Eq{$Version}{$Base}) {
2158 next;
2159 }
2160 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2161 if($#Translations==0)
2162 {
2163 if(length($Translations[0])<=length($Base)) {
2164 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2165 }
2166 }
2167 else
2168 { # select most appropriate
2169 foreach my $Tr (@Translations)
2170 {
2171 if($Base=~/\A\Q$Tr\E/)
2172 {
2173 $Typedef_Eq{$Version}{$Base} = $Tr;
2174 last;
2175 }
2176 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002177 }
2178 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002179 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002180 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002181 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002182 if(not $TypeName) {
2183 next;
2184 }
2185 next if(index($TypeName,"<")==-1);# template instances only
2186 if($TypeName=~/>(::\w+)+\Z/)
2187 { # skip unused types
2188 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002189 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002190 foreach my $Base (sort {length($b)<=>length($a)}
2191 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002192 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002193 next if(not $Base);
2194 next if(index($TypeName,$Base)==-1);
2195 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002196 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002197 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002198 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2199 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2200 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002201 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002202 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2203 {
2204 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2205 {
2206 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2207 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002208 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002209 }
2210 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002214 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002215 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2216 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002217 }
2218}
2219
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002220sub setAnonTypedef_All()
2221{
2222 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2223 {
2224 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2225 {
2226 if(isAnon(getNameByInfo($InfoId))) {
2227 $TypedefToAnon{getTypeId($InfoId)} = 1;
2228 }
2229 }
2230 }
2231}
2232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002233sub setTemplateParams_All()
2234{
2235 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2236 {
2237 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2238 setTemplateParams($_);
2239 }
2240 }
2241}
2242
2243sub setTemplateParams($)
2244{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002245 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002246 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002247 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002248 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002250 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002251 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002252 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002253 setTemplateInstParams($_[0], $TmplInst_Id);
2254 }
2255 }
2256
2257 $BasicTemplate{$Version}{$Tid} = $_[0];
2258
2259 if(my $Prms = getTreeAttr_Prms($_[0]))
2260 {
2261 if(my $Valu = getTreeAttr_Valu($Prms))
2262 {
2263 my $Vector = getTreeVec($Valu);
2264 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2265 {
2266 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2267 {
2268 if(my $Name = getNameByInfo($Val))
2269 {
2270 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2271 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2272 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2273 }
2274 else {
2275 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2276 }
2277 }
2278 }
2279 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002281 }
2282 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002283 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002284 {
2285 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2286 {
2287 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002288 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002289 }
2290 }
2291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002292}
2293
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002294sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002296 my ($Tmpl, $Inst) = @_;
2297
2298 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002299 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002300 my ($Params_InfoId, $ElemId) = ();
2301 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2302 $Params_InfoId = $1;
2303 }
2304 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2305 $ElemId = $1;
2306 }
2307 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002308 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002309 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2310 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2311 {
2312 my ($PPos, $PTypeId) = ($1, $2);
2313 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2314 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002315 if($PType eq "template_type_parm") {
2316 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002317 }
2318 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002319 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2320 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002321 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002322 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002323 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002324 else
2325 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002326 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002327 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002328 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002329 }
2330 }
2331 }
2332}
2333
2334sub getTypeDeclId($)
2335{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002336 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002337 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002338 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2339 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2340 }
2341 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2342 {
2343 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2344 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2345 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002348 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002349}
2350
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002351sub getTypeInfo_All()
2352{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002353 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002354 { # support for GCC < 4.5
2355 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2356 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2357 # FIXME: check GCC versions
2358 addMissedTypes_Pre();
2359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002361 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002362 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2364 if($IType=~/_type\Z/ and $IType ne "function_type"
2365 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002366 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002367 }
2368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002369
2370 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002371 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002372 "Name" => "...",
2373 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002374 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002375 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002376 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002377
2378 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002379 { # support for GCC < 4.5
2380 addMissedTypes_Post();
2381 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002382
2383 if($ADD_TMPL_INSTANCES)
2384 {
2385 # templates
2386 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2387 {
2388 if(defined $TemplateMap{$Version}{$Tid}
2389 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2390 {
2391 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2392 {
2393 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2394 {
2395 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2396 {
2397 if(my %MAttr = getTypeAttr($MembTypeId))
2398 {
2399 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2400 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2401 }
2402 }
2403 }
2404 }
2405 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2406 {
2407 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2408 {
2409 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2410
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002411 if($NBid ne $Bid
2412 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002413 {
2414 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2415 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2416 }
2417 }
2418 }
2419 }
2420 }
2421 }
2422}
2423
2424sub createType($$)
2425{
2426 my ($Attr, $LibVersion) = @_;
2427 my $NewId = ++$MAX_ID;
2428
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002429 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002430 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002431 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002432
2433 return "$NewId";
2434}
2435
2436sub instType($$$)
2437{ # create template instances
2438 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002439
2440 if(not $TypeInfo{$LibVersion}{$Tid}) {
2441 return undef;
2442 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002443 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2444
2445 foreach my $Key (sort keys(%{$Map}))
2446 {
2447 if(my $Val = $Map->{$Key})
2448 {
2449 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2450
2451 if(defined $Attr->{"NameSpace"}) {
2452 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2453 }
2454 foreach (keys(%{$Attr->{"TParam"}})) {
2455 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2456 }
2457 }
2458 else
2459 { # remove absent
2460 # _Traits, etc.
2461 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002462 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002463 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2464 }
2465 foreach (keys(%{$Attr->{"TParam"}}))
2466 {
2467 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2468 delete($Attr->{"TParam"}{$_});
2469 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002470 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002471 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2472 }
2473 }
2474 }
2475 }
2476
2477 my $Tmpl = 0;
2478
2479 if(defined $Attr->{"TParam"})
2480 {
2481 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2482 {
2483 my $PName = $Attr->{"TParam"}{$_}{"name"};
2484
2485 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2486 {
2487 my %Base = get_BaseType($PTid, $LibVersion);
2488
2489 if($Base{"Type"} eq "TemplateParam"
2490 or defined $Base{"Template"})
2491 {
2492 $Tmpl = 1;
2493 last
2494 }
2495 }
2496 }
2497 }
2498
2499 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2500 return "$Id";
2501 }
2502 else
2503 {
2504 if(not $Tmpl) {
2505 delete($Attr->{"Template"});
2506 }
2507
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002508 my $New = createType($Attr, $LibVersion);
2509
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002510 my %EMap = ();
2511 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2512 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2513 }
2514 foreach (keys(%{$Map})) {
2515 $EMap{$_} = $Map->{$_};
2516 }
2517
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002518 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2519 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002520 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002521 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002522 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002523 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002524 {
2525 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2526
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002527 if($NBid ne $Bid
2528 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002530 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2531 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002532 }
2533 }
2534 }
2535
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002536 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002537 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002538 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2539 {
2540 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2541 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2542 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002543 }
2544 }
2545
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002546 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002547 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002548 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2549 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002550 }
2551 }
2552
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002553 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2554 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002555 }
2556
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002557 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002559}
2560
2561sub addMissedTypes_Pre()
2562{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002563 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002564 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2565 { # detecting missed typedefs
2566 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2567 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002568 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002569 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002570 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002571 if($TypeType eq "Unknown")
2572 { # template_type_parm
2573 next;
2574 }
2575 my $TypeDeclId = getTypeDeclId($TypeId);
2576 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2577 my $TypedefName = getNameByInfo($MissedTDid);
2578 next if(not $TypedefName);
2579 next if($TypedefName eq "__float80");
2580 next if(isAnon($TypedefName));
2581 if(not $TypeDeclId
2582 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002583 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002584 }
2585 }
2586 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002587 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002588 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002589 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002590 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002591 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 next;
2593 }
2594 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002595 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002596 if(not $TypedefName) {
2597 next;
2598 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002599 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 my %MissedInfo = ( # typedef info
2601 "Name" => $TypedefName,
2602 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002603 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002604 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002605 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 my ($H, $L) = getLocation($MissedTDid);
2607 $MissedInfo{"Header"} = $H;
2608 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002609 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # other types
2611 next;
2612 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002613 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 next;
2616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002617 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002619 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002621 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002623 next;
2624 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002625 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 next;
2627 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002628 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 next;
2631 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002632 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002633 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002634 next;
2635 }
2636 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002637
2638 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002640 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002641 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002642 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002643 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002644 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002645
2646 # add missed & remove other
2647 $TypeInfo{$Version} = \%AddTypes;
2648 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002649}
2650
2651sub addMissedTypes_Post()
2652{
2653 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2654 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002655 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2656 {
2657 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2658 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2659 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2660 }
2661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002662 }
2663}
2664
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002665sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002666{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002667 my $TypeId = $_[0];
2668 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2669 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002670 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002671 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002672 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002673}
2674
2675sub getArraySize($$)
2676{
2677 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002678 if(my $Size = getSize($TypeId))
2679 {
2680 my $Elems = $Size/$BYTE_SIZE;
2681 while($BaseName=~s/\s*\[(\d+)\]//) {
2682 $Elems/=$1;
2683 }
2684 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2685 {
2686 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2687 $Elems/=$BasicSize;
2688 }
2689 }
2690 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002691 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002692 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002693}
2694
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002695sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002696{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002697 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002698 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002699 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2700 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002701 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002702 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2703 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2704 if(not $NodeType)
2705 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002706 return ();
2707 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002708 if($NodeType eq "tree_vec")
2709 {
2710 if($Pos!=$#Positions)
2711 { # select last vector of parameters ( ns<P1>::type<P2> )
2712 next;
2713 }
2714 }
2715 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2716 foreach my $P (@Params)
2717 {
2718 if($P eq "") {
2719 return ();
2720 }
2721 elsif($P ne "\@skip\@") {
2722 @TmplParams = (@TmplParams, $P);
2723 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002724 }
2725 }
2726 return @TmplParams;
2727}
2728
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002729sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002730{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002731 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002732 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002733 if(defined $TypeInfo{$Version}{$TypeId}
2734 and $TypeInfo{$Version}{$TypeId}{"Name"})
2735 { # already created
2736 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002737 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002738 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2739 { # incomplete type
2740 return ();
2741 }
2742 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2743
2744 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002745 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002746
2747 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2748 {
2749 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2750 {
2751 if($Info=~/qual[ ]*:/)
2752 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002753 my $NewId = ++$MAX_ID;
2754
2755 $MissedBase{$Version}{$TypeId} = "$NewId";
2756 $MissedBase_R{$Version}{$NewId} = $TypeId;
2757 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2758 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002759 }
2760 }
2761 $TypeAttr{"Type"} = "Typedef";
2762 }
2763 else {
2764 $TypeAttr{"Type"} = getTypeType($TypeId);
2765 }
2766
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002767 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2768 {
2769 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2770 { # local code
2771 return ();
2772 }
2773 }
2774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775 if($TypeAttr{"Type"} eq "Unknown") {
2776 return ();
2777 }
2778 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002780 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002781 if(my $TName = $TypeAttr{"Name"})
2782 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002783 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002784 $TName_Tid{$Version}{$TName} = $TypeId;
2785 return %TypeAttr;
2786 }
2787 else {
2788 return ();
2789 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002790 }
2791 elsif($TypeAttr{"Type"} eq "Array")
2792 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002793 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2794 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002795 return ();
2796 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002797 if(my $Algn = getAlgn($TypeId)) {
2798 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2799 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002800 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002801 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002802 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002803 if(not $BTAttr{"Name"}) {
2804 return ();
2805 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002806 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002807 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002808 if(my $Size = getSize($TypeId)) {
2809 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2810 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002811 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002812 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2813 }
2814 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002815 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002818 else
2819 {
2820 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002821 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002822 $TypeAttr{"Name"} = $1."[]".$2;
2823 }
2824 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002825 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002828 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002829 if($BTAttr{"Header"}) {
2830 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002831 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002832 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002833 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2834 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002835 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002836 return ();
2837 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002838 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002839 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002840 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002841 if($TypeAttr{"Name"})
2842 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002843 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002844
2845 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2846 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002847 { # NOTE: register only one int: with built-in decl
2848 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2849 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2850 }
2851 }
2852 return %TypeAttr;
2853 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002854 else {
2855 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002857 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002858 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2859 {
2860 %TypeAttr = getTrivialTypeAttr($TypeId);
2861 if($TypeAttr{"Name"})
2862 {
2863 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2864 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2865 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2866 }
2867 return %TypeAttr;
2868 }
2869 else {
2870 return ();
2871 }
2872 }
2873 elsif($TypeAttr{"Type"} eq "SizeOf")
2874 {
2875 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2876 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2877 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2878 if($TypeAttr{"Name"})
2879 {
2880 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2881 return %TypeAttr;
2882 }
2883 else {
2884 return ();
2885 }
2886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002887 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002888 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002889 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2890 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002891 return ();
2892 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002893 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002894 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002895 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002896 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002897 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002898 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002899 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 }
2902 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002903 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002904 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002905 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 return ();
2907 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002908 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002910 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002911 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002912 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002913 }
2914 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002915 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002916 {
2917 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002918 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002919 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002920 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002921 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2922 }
2923 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002924 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002925 }
2926 }
2927 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002928 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002929 }
2930 if($TypeAttr{"Type"} eq "Typedef")
2931 {
2932 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002933
2934 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2935 return ();
2936 }
2937
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002938 if(isAnon($TypeAttr{"Name"}))
2939 { # anon typedef to anon type: ._N
2940 return ();
2941 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002942
2943 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2944 { # artificial typedef of "struct X" to "X"
2945 $TypeAttr{"Artificial"} = 1;
2946 }
2947
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002948 if(my $NS = getNameSpace($TypeDeclId))
2949 {
2950 my $TypeName = $TypeAttr{"Name"};
2951 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2952 { # "some_type" is the typedef to "struct some_type" in C++
2953 if($3) {
2954 $TypeAttr{"Name"} = $3."::".$TypeName;
2955 }
2956 }
2957 else
2958 {
2959 $TypeAttr{"NameSpace"} = $NS;
2960 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002961
2962 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2963 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2964 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 if($BTAttr{"NameSpace"}
2966 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002967 { # types like "std::fpos<__mbstate_t>" are
2968 # not covered by typedefs in the TU dump
2969 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2971 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002972 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002973 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002974 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002975 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002976 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002977 }
2978 }
2979 }
2980 }
2981 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002982 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002983 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002985 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2986 { # typedef int*const TYPEDEF; // first
2987 # int foo(TYPEDEF p); // const is optimized out
2988 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2989 if($BTAttr{"Name"}=~/</)
2990 {
2991 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2992 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 }
2995 }
2996 }
2997 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2998 }
2999 if(not $TypeAttr{"Size"})
3000 {
3001 if($TypeAttr{"Type"} eq "Pointer") {
3002 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3003 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003004 elsif($BTAttr{"Size"}) {
3005 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003006 }
3007 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003008 if(my $Algn = getAlgn($TypeId)) {
3009 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3010 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003011 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003012 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3013 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003014 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003015 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003016 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003017 { # typedef to "class Class"
3018 # should not be registered in TName_Tid
3019 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3020 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003022 }
3023 return %TypeAttr;
3024 }
3025}
3026
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003027sub getTreeVec($)
3028{
3029 my %Vector = ();
3030 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3031 {
3032 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3033 { # string length is N-1 because of the null terminator
3034 $Vector{$1} = $2;
3035 }
3036 }
3037 return \%Vector;
3038}
3039
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040sub get_TemplateParam($$)
3041{
3042 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003043 return () if(not $Type_Id);
3044 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3045 return () if(not $NodeType);
3046 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003048 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003049 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 my $Num = getNodeIntCst($Type_Id);
3051 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003052 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003053 }
3054 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003055 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003056 }
3057 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003058 elsif($NodeType eq "string_cst") {
3059 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003061 elsif($NodeType eq "tree_vec")
3062 {
3063 my $Vector = getTreeVec($Type_Id);
3064 my @Params = ();
3065 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3066 {
3067 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3068 push(@Params, $P2);
3069 }
3070 }
3071 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003072 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003073 elsif($NodeType eq "parm_decl")
3074 {
3075 (getNameByInfo($Type_Id));
3076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003077 else
3078 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003079 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003080 my $PName = $ParamAttr{"Name"};
3081 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003082 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003083 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003084 if($PName=~/\>/)
3085 {
3086 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003087 $PName = $Cover;
3088 }
3089 }
3090 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003091 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003092 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3093 # template<typename _Key, typename _Compare = std::less<_Key>
3094 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3095 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3096 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3097 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003098 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003100 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003101 }
3102}
3103
3104sub cover_stdcxx_typedef($)
3105{
3106 my $TypeName = $_[0];
3107 if(my @Covers = sort {length($a)<=>length($b)}
3108 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3109 { # take the shortest typedef
3110 # FIXME: there may be more than
3111 # one typedefs to the same type
3112 return $Covers[0];
3113 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003114 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003115 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3116 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3117 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003118 if(my $Cover = $Covers[0])
3119 {
3120 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3121 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003124 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003125}
3126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127sub getNodeIntCst($)
3128{
3129 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003130 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003131 if($EnumMembName_Id{$Version}{$CstId}) {
3132 return $EnumMembName_Id{$Version}{$CstId};
3133 }
3134 elsif((my $Value = getTreeValue($CstId)) ne "")
3135 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003136 if($Value eq "0")
3137 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003138 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003139 return "false";
3140 }
3141 else {
3142 return "0";
3143 }
3144 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003145 elsif($Value eq "1")
3146 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003147 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003148 return "true";
3149 }
3150 else {
3151 return "1";
3152 }
3153 }
3154 else {
3155 return $Value;
3156 }
3157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003158 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003159}
3160
3161sub getNodeStrCst($)
3162{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003163 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3164 {
3165 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003166 {
3167 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3168 { # string length is N-1 because of the null terminator
3169 return substr($1, 0, $2-1);
3170 }
3171 else
3172 { # identifier_node
3173 return substr($1, 0, $2);
3174 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003175 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003176 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003177 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178}
3179
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003180sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003181{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003182 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003183 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3184 if($Type eq "FieldPtr") {
3185 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3186 }
3187 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3188 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003189 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003190 if($Type eq "MethodPtr")
3191 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003192 if(my $Size = getSize($TypeId))
3193 {
3194 $Size/=$BYTE_SIZE;
3195 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003197 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003198 if(my $Algn = getAlgn($TypeId)) {
3199 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003201 # Return
3202 if($Type eq "FieldPtr")
3203 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003204 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003205 if($ReturnAttr{"Name"}) {
3206 $MemPtrName .= $ReturnAttr{"Name"};
3207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003208 $TypeAttr{"Return"} = $PtrId;
3209 }
3210 else
3211 {
3212 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3213 {
3214 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003215 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3216 if(not $ReturnAttr{"Name"})
3217 { # templates
3218 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003219 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003220 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003221 $TypeAttr{"Return"} = $ReturnTypeId;
3222 }
3223 }
3224 # Class
3225 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3226 {
3227 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003228 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003229 if($Class{"Name"}) {
3230 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3231 }
3232 else {
3233 $MemPtrName .= " (*)";
3234 }
3235 }
3236 else {
3237 $MemPtrName .= " (*)";
3238 }
3239 # Parameters
3240 if($Type eq "FuncPtr"
3241 or $Type eq "MethodPtr")
3242 {
3243 my @ParamTypeName = ();
3244 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3245 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003246 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003247 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003248 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003249 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003250 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3251 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003252 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003253 my $PTypeId = $1;
3254 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 if(not $ParamAttr{"Name"})
3256 { # templates (template_type_parm), etc.
3257 return ();
3258 }
3259 if($ParamAttr{"Name"} eq "void") {
3260 last;
3261 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003262 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003263 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003264 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003265 push(@ParamTypeName, $ParamAttr{"Name"});
3266 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003267 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3268 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003269 }
3270 else {
3271 last;
3272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003273 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003274 else {
3275 last;
3276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003277 }
3278 }
3279 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3280 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003281 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003282 return %TypeAttr;
3283}
3284
3285sub getTreeTypeName($)
3286{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003287 my $TypeId = $_[0];
3288 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003289 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003290 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003291 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292 if(my $Name = getNameByInfo($TypeId))
3293 { # bit_size_type
3294 return $Name;
3295 }
3296 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297 return "unsigned int";
3298 }
3299 else {
3300 return "int";
3301 }
3302 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003303 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 return getNameByInfo($1);
3305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003306 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003307 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308}
3309
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003310sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003311{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003312 my $Ptd = pointTo($_[0]);
3313 return 0 if(not $Ptd);
3314 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003315 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003316 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3317 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003318 }
3319 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003320 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3321 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003322 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003323 if($InfoT1 eq "pointer_type"
3324 and $InfoT2 eq "function_type") {
3325 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003326 }
3327 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003328 return 0;
3329}
3330
3331sub isMethodPtr($)
3332{
3333 my $Ptd = pointTo($_[0]);
3334 return 0 if(not $Ptd);
3335 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3336 {
3337 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3338 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3339 and $Info=~/ ptrmem /) {
3340 return 1;
3341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003342 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003343 return 0;
3344}
3345
3346sub isFieldPtr($)
3347{
3348 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3349 {
3350 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3351 and $Info=~/ ptrmem /) {
3352 return 1;
3353 }
3354 }
3355 return 0;
3356}
3357
3358sub pointTo($)
3359{
3360 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3361 {
3362 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3363 return $1;
3364 }
3365 }
3366 return "";
3367}
3368
3369sub getTypeTypeByTypeId($)
3370{
3371 my $TypeId = $_[0];
3372 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3373 {
3374 my $NType = $NodeType{$TType};
3375 if($NType eq "Intrinsic") {
3376 return $NType;
3377 }
3378 elsif(isFuncPtr($TypeId)) {
3379 return "FuncPtr";
3380 }
3381 elsif(isMethodPtr($TypeId)) {
3382 return "MethodPtr";
3383 }
3384 elsif(isFieldPtr($TypeId)) {
3385 return "FieldPtr";
3386 }
3387 elsif($NType ne "Other") {
3388 return $NType;
3389 }
3390 }
3391 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003392}
3393
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003394my %UnQual = (
3395 "r"=>"restrict",
3396 "v"=>"volatile",
3397 "c"=>"const",
3398 "cv"=>"const volatile"
3399);
3400
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003401sub getQual($)
3402{
3403 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003404 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3405 {
3406 my ($Qual, $To) = ();
3407 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3408 $Qual = $UnQual{$1};
3409 }
3410 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3411 $To = $1;
3412 }
3413 if($Qual and $To) {
3414 return ($Qual, $To);
3415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003416 }
3417 return ();
3418}
3419
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003420sub getQualType($)
3421{
3422 if($_[0] eq "const volatile") {
3423 return "ConstVolatile";
3424 }
3425 return ucfirst($_[0]);
3426}
3427
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003428sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003429{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003430 my $TypeId = $_[0];
3431 my $TypeDeclId = getTypeDeclId($TypeId);
3432 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003433 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003434 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3435 return "Typedef";
3436 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003437 }
3438 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3439 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003440 if(($Qual or $To) and $TypeDeclId
3441 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003442 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003443 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003445 elsif(not $MissedBase_R{$Version}{$TypeId}
3446 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003447 return "Typedef";
3448 }
3449 elsif($Qual)
3450 { # qualified types
3451 return getQualType($Qual);
3452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003453
3454 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3455 { # typedef struct { ... } name
3456 $TypeTypedef{$Version}{$TypeId} = $1;
3457 }
3458
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003459 my $TypeType = getTypeTypeByTypeId($TypeId);
3460 if($TypeType eq "Struct")
3461 {
3462 if($TypeDeclId
3463 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3464 return "Template";
3465 }
3466 }
3467 return $TypeType;
3468}
3469
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003470sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003471{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003472 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003473 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003474 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3475 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3476 return 0;
3477 }
3478 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3479 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003480 if(my $TDid = getTypeDeclId($_[0]))
3481 {
3482 if(getTypeId($TDid) eq $_[0]
3483 and getNameByInfo($TDid))
3484 {
3485 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3486 return $1;
3487 }
3488 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003489 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003490 }
3491 }
3492 return 0;
3493}
3494
3495sub selectBaseType($)
3496{
3497 my $TypeId = $_[0];
3498 if(defined $MissedTypedef{$Version}{$TypeId})
3499 { # add missed typedefs
3500 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3501 return ($TypeId, "");
3502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003503 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003504 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3505 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003506
3507 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3508 my $MB = $MissedBase{$Version}{$TypeId};
3509
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003510 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003511 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003512 and (getTypeId($1) ne $TypeId)
3513 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003514 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003517 elsif($MB)
3518 { # add base
3519 return ($MB, "");
3520 }
3521 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003523 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003524 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003525 elsif($Qual or $To)
3526 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003527 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003529 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003530 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003531 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003532 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003535 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003536 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003537 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003538 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003540 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003541 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003542 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003543 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003544 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003546 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003547
3548 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003549}
3550
3551sub getSymbolInfo_All()
3552{
3553 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3554 { # reverse order
3555 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003556 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003557 }
3558 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003559
3560 if($ADD_TMPL_INSTANCES)
3561 {
3562 # templates
3563 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3564 {
3565 my %Map = ();
3566
3567 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3568 {
3569 if(defined $TemplateMap{$Version}{$ClassId})
3570 {
3571 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3572 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3573 }
3574 }
3575 }
3576
3577 if(defined $TemplateMap{$Version}{$Sid})
3578 {
3579 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3580 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3581 }
3582 }
3583
3584 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3585 {
3586 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3587 {
3588 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3589 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3590 }
3591 }
3592 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3593 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3594 }
3595 }
3596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003597}
3598
3599sub getVarInfo_All()
3600{
3601 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3602 { # reverse order
3603 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003604 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003605 }
3606 }
3607}
3608
3609sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003610 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003611}
3612
3613sub getVarInfo($)
3614{
3615 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003616 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003617 {
3618 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3619 if($NSInfoType and $NSInfoType eq "function_decl") {
3620 return;
3621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003622 }
3623 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3624 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3625 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3626 delete($SymbolInfo{$Version}{$InfoId});
3627 return;
3628 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003629 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003630 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003631 delete($SymbolInfo{$Version}{$InfoId});
3632 return;
3633 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003634 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3635 delete($SymbolInfo{$Version}{$InfoId});
3636 return;
3637 }
3638 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003639 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3640 {
3641 if($OSgroup eq "windows")
3642 { # cut the offset
3643 $MnglName=~s/\@\d+\Z//g;
3644 }
3645 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003647 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003648 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003649 { # validate mangled name
3650 delete($SymbolInfo{$Version}{$InfoId});
3651 return;
3652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003654 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003655 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003656 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003657 }
3658 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3659 { # non-public global data
3660 delete($SymbolInfo{$Version}{$InfoId});
3661 return;
3662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003663 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003665 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003666 if(not defined $TypeInfo{$Version}{$Rid}
3667 or not $TypeInfo{$Version}{$Rid}{"Name"})
3668 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003669 delete($SymbolInfo{$Version}{$InfoId});
3670 return;
3671 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003672 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3673 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003674 if(defined $Val) {
3675 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 }
3678 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003679 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3680 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003681 if(not defined $TypeInfo{$Version}{$ClassId}
3682 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003684 delete($SymbolInfo{$Version}{$InfoId});
3685 return;
3686 }
3687 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003688 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3689 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003690 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003691 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003692 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003693 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003695 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003696 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003697 if(not $CheckHeadersOnly)
3698 {
3699 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3700 {
3701 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3702 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3703 {
3704 if(link_symbol($ShortName, $Version, "-Deps"))
3705 { # "const" global data is mangled as _ZL... in the TU dump
3706 # but not mangled when compiling a C shared library
3707 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3708 }
3709 }
3710 }
3711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003712 if($COMMON_LANGUAGE{$Version} eq "C++")
3713 {
3714 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3715 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003716 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003717 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3718 }
3719 }
3720 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3721 { # try to mangle symbol (link with libraries)
3722 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3723 }
3724 if($OStarget eq "windows")
3725 {
3726 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3727 { # link MS C++ symbols from library with GCC symbols from headers
3728 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3729 }
3730 }
3731 }
3732 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3733 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3734 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003735 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3736 {
3737 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3738 { # non-target symbols
3739 delete($SymbolInfo{$Version}{$InfoId});
3740 return;
3741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003743 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3744 {
3745 if(defined $MissedTypedef{$Version}{$Rid})
3746 {
3747 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3748 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3749 }
3750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003751 }
3752 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003753 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003754 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3755 }
3756 if($ShortName=~/\A(_Z|\?)/) {
3757 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3758 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003759
3760 if($ExtraDump) {
3761 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763}
3764
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003765sub isConstType($$)
3766{
3767 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003768 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003769 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003770 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003771 }
3772 return ($Base{"Type"} eq "Const");
3773}
3774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003775sub getTrivialName($$)
3776{
3777 my ($TypeInfoId, $TypeId) = @_;
3778 my %TypeAttr = ();
3779 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3780 if(not $TypeAttr{"Name"}) {
3781 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3782 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003783 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003784 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003785 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003786 if(isAnon($TypeAttr{"Name"}))
3787 {
3788 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003789 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003790 { # searching for a first not anon scope
3791 if($NSId eq $NameSpaceId) {
3792 last;
3793 }
3794 else
3795 {
3796 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3797 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003798 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003799 last;
3800 }
3801 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003802 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003803 }
3804 }
3805 else
3806 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003807 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003808 {
3809 if($NameSpaceId ne $TypeId) {
3810 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 }
3813 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003814 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003815 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3816 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003817 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003818 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003819 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003820 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003822 if($TypeAttr{"NameSpace"}) {
3823 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003825 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003826 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3827 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003829 if(my @TParams = getTParams($TypeId, "Type")) {
3830 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3831 }
3832 else {
3833 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3834 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003835 }
3836 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3837}
3838
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003839sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003840{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003841 my $TypeId = $_[0];
3842 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003843
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003844 my %TypeAttr = ();
3845
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003846 if($TemplateDecl{$Version}{$TypeId})
3847 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003848 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003849 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003850
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003851 setTypeAccess($TypeId, \%TypeAttr);
3852 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3853 if(isBuiltIn($TypeAttr{"Header"}))
3854 {
3855 delete($TypeAttr{"Header"});
3856 delete($TypeAttr{"Line"});
3857 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003858
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003859 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003860 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3861 if(not $TypeAttr{"Name"}) {
3862 return ();
3863 }
3864 if(not $TypeAttr{"NameSpace"}) {
3865 delete($TypeAttr{"NameSpace"});
3866 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003867
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003868 if($TypeAttr{"Type"} eq "Intrinsic")
3869 {
3870 if(defined $TypeAttr{"Header"})
3871 {
3872 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3873 { # support for SUSE 11.2
3874 # integer_type has srcp dump{1-2}.i
3875 delete($TypeAttr{"Header"});
3876 }
3877 }
3878 }
3879
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003880 my $Tmpl = undef;
3881
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003882 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003883 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003884 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3885
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003886 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003887 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003888 foreach my $Pos (0 .. $#TParams)
3889 {
3890 my $Val = $TParams[$Pos];
3891 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3892
3893 if(not defined $TypeAttr{"Template"})
3894 {
3895 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3896
3897 if($Base{"Type"} eq "TemplateParam"
3898 or defined $Base{"Template"}) {
3899 $TypeAttr{"Template"} = 1;
3900 }
3901 }
3902
3903 if($Tmpl)
3904 {
3905 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3906 {
3907 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3908
3909 if($Val eq $Arg) {
3910 $TypeAttr{"Template"} = 1;
3911 }
3912 }
3913 }
3914 }
3915
3916 if($Tmpl)
3917 {
3918 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3919 {
3920 if($Pos>$#TParams)
3921 {
3922 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3923 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3924 }
3925 }
3926 }
3927 }
3928
3929 if($ADD_TMPL_INSTANCES)
3930 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003931 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003932 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003933 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003934 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003935 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003936 {
3937 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3938 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3939 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003940 }
3941 if(not getTreeAttr_Binf($TypeId))
3942 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003943 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3944 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3945 }
3946 }
3947 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003948 }
3949 }
3950 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003951
3952 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3953
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003954 if(my $Size = getSize($TypeId))
3955 {
3956 $Size = $Size/$BYTE_SIZE;
3957 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003958 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003959 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003960 {
3961 if($ExtraDump)
3962 {
3963 if(not defined $TypeAttr{"Memb"}
3964 and not $Tmpl)
3965 { # declaration only
3966 $TypeAttr{"Forward"} = 1;
3967 }
3968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003969 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003970
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003971 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003972 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 {
3974 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003975 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003976 }
3977 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003978 or $TypeAttr{"Type"} eq "Class")
3979 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003980 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003981 if($Skip) {
3982 return ();
3983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003984 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003985 if(my $Algn = getAlgn($TypeId)) {
3986 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003988 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003989
3990 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3991 {
3992 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003993 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003994 {
3995 if(not isAnon($TypeAttr{"Name"})) {
3996 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3997 }
3998 }
3999 }
4000
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004001 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004002 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4003 {
4004 my @Entries = split(/\n/, $VTable);
4005 foreach (1 .. $#Entries)
4006 {
4007 my $Entry = $Entries[$_];
4008 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004009 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004010 }
4011 }
4012 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004013
4014 if($TypeAttr{"Type"} eq "Enum")
4015 {
4016 if(not $TypeAttr{"NameSpace"})
4017 {
4018 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4019 {
4020 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004021 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004022 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004023 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004024 "Header"=>$TypeAttr{"Header"}
4025 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004026 if(isAnon($TypeAttr{"Name"}))
4027 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004028 if($ExtraDump
4029 or is_target_header($TypeAttr{"Header"}, $Version))
4030 {
4031 %{$Constants{$Version}{$MName}} = (
4032 "Value" => $MVal,
4033 "Header" => $TypeAttr{"Header"}
4034 );
4035 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004036 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004037 }
4038 }
4039 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004040 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004041 {
4042 if(defined $TypedefToAnon{$TypeId}) {
4043 $TypeAttr{"AnonTypedef"} = 1;
4044 }
4045 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004047 return %TypeAttr;
4048}
4049
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004050sub simplifyVTable($)
4051{
4052 my $Content = $_[0];
4053 if($Content=~s/ \[with (.+)]//)
4054 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4055 if(my @Elems = separate_Params($1, 0, 0))
4056 {
4057 foreach my $Elem (@Elems)
4058 {
4059 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4060 {
4061 my ($Arg, $Val) = ($1, $2);
4062
4063 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4064 $Content=~s/,\s*$Arg\b//g;
4065 }
4066 else {
4067 $Content=~s/\b$Arg\b/$Val/g;
4068 }
4069 }
4070 }
4071 }
4072 }
4073
4074 return $Content;
4075}
4076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004077sub detect_lang($)
4078{
4079 my $TypeId = $_[0];
4080 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004081 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004082 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004083 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4084 }
4085 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004086 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004087 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004088 while($Fncs)
4089 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004090 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004091 return 1;
4092 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004093 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004094 }
4095 }
4096 return 0;
4097}
4098
4099sub setSpec($$)
4100{
4101 my ($TypeId, $TypeAttr) = @_;
4102 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4103 if($Info=~/\s+spec\s+/) {
4104 $TypeAttr->{"Spec"} = 1;
4105 }
4106}
4107
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004108sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004109{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004110 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004112 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004113 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004114 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004115 my $Pos = 0;
4116 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4117 {
4118 my ($Access, $BInfoId) = ($1, $2);
4119 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004120
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004121 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004122 { # class A<N>:public A<N-1>
4123 next;
4124 }
4125
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004126 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4127 if(not $CType or $CType eq "template_type_parm"
4128 or $CType eq "typename_type")
4129 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004130 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004133 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4135 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004136 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4138 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004139 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004140 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004141 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004142 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4143 }
4144 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004145 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004146 }
4147 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004148 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004149}
4150
4151sub getBinfClassId($)
4152{
4153 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03004154 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4155 return $1;
4156 }
4157
4158 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159}
4160
4161sub unmangledFormat($$)
4162{
4163 my ($Name, $LibVersion) = @_;
4164 $Name = uncover_typedefs($Name, $LibVersion);
4165 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4166 $Name=~s/\(\w+\)(\d)/$1/;
4167 return $Name;
4168}
4169
4170sub modelUnmangled($$)
4171{
4172 my ($InfoId, $Compiler) = @_;
4173 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4174 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4175 }
4176 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4177 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4178 $PureSignature = "~".$PureSignature;
4179 }
4180 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4181 {
4182 my (@Params, @ParamTypes) = ();
4183 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4184 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4185 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4186 }
4187 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4188 { # checking parameters
4189 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004190 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004191 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004193
4194 if($PName eq "this"
4195 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4196 {
4197 next;
4198 }
4199
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004200 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004201 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004202 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004203 }
4204 @ParamTypes = (@ParamTypes, $PTName);
4205 }
4206 if(@ParamTypes) {
4207 $PureSignature .= "(".join(", ", @ParamTypes).")";
4208 }
4209 else
4210 {
4211 if($Compiler eq "MSVC")
4212 {
4213 $PureSignature .= "(void)";
4214 }
4215 else
4216 { # GCC
4217 $PureSignature .= "()";
4218 }
4219 }
4220 $PureSignature = delete_keywords($PureSignature);
4221 }
4222 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4223 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004224 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004225 $PureSignature = $ClassName."::".$PureSignature;
4226 }
4227 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4228 $PureSignature = $NS."::".$PureSignature;
4229 }
4230 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4231 $PureSignature .= " const";
4232 }
4233 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4234 $PureSignature .= " volatile";
4235 }
4236 my $ShowReturn = 0;
4237 if($Compiler eq "MSVC"
4238 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4239 {
4240 $ShowReturn=1;
4241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004242 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4243 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004244 {
4245 $ShowReturn=1;
4246 }
4247 if($ShowReturn)
4248 { # mangled names for template function specializations include return value
4249 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4250 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004251 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004252 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4253 $PureSignature = $ReturnName." ".$PureSignature;
4254 }
4255 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004256 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257}
4258
4259sub mangle_symbol($$$)
4260{ # mangling for simple methods
4261 # see gcc-4.6.0/gcc/cp/mangle.c
4262 my ($InfoId, $LibVersion, $Compiler) = @_;
4263 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4264 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4265 }
4266 my $Mangled = "";
4267 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004268 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004269 }
4270 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004271 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004272 }
4273 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4274}
4275
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004276sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004277{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004278 my ($InfoId, $LibVersion) = @_;
4279 return "";
4280}
4281
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004282sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004283{ # see gcc-4.6.0/gcc/cp/mangle.c
4284 my ($InfoId, $LibVersion) = @_;
4285 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004286 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004287 my %Repl = ();# SN_ replacements
4288 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4289 {
4290 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4291 if($MangledClass!~/\AN/) {
4292 $MangledClass = "N".$MangledClass;
4293 }
4294 else {
4295 $MangledClass=~s/E\Z//;
4296 }
4297 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4298 $MangledClass=~s/\AN/NV/;
4299 }
4300 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4301 $MangledClass=~s/\AN/NK/;
4302 }
4303 $Mangled .= $MangledClass;
4304 }
4305 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4306 { # mangled by name due to the absence of structured info
4307 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4308 if($MangledNS!~/\AN/) {
4309 $MangledNS = "N".$MangledNS;
4310 }
4311 else {
4312 $MangledNS=~s/E\Z//;
4313 }
4314 $Mangled .= $MangledNS;
4315 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004316 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004317 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004318 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004319 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004320 foreach (@TPos) {
4321 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4322 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004323 }
4324 elsif($TmplParams)
4325 { # remangling mode
4326 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004327 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004328 }
4329 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4330 $Mangled .= "C1";
4331 }
4332 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4333 $Mangled .= "D0";
4334 }
4335 elsif($ShortName)
4336 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004337 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4338 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004339 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004340 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004341 { # "const" global data is mangled as _ZL...
4342 $Mangled .= "L";
4343 }
4344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004345 if($ShortName=~/\Aoperator(\W.*)\Z/)
4346 {
4347 my $Op = $1;
4348 $Op=~s/\A[ ]+//g;
4349 if(my $OpMngl = $OperatorMangling{$Op}) {
4350 $Mangled .= $OpMngl;
4351 }
4352 else { # conversion operator
4353 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4354 }
4355 }
4356 else {
4357 $Mangled .= length($ShortName).$ShortName;
4358 }
4359 if(@TParams)
4360 { # templates
4361 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004362 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004363 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4364 }
4365 $Mangled .= "E";
4366 }
4367 if(not $ClassId and @TParams) {
4368 add_substitution($ShortName, \%Repl, 0);
4369 }
4370 }
4371 if($ClassId or $NameSpace) {
4372 $Mangled .= "E";
4373 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004374 if(@TParams)
4375 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004376 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004377 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4378 }
4379 }
4380 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4381 {
4382 my @Params = ();
4383 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4384 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4385 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4386 }
4387 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4388 { # checking parameters
4389 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4390 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4391 }
4392 if(not @Params) {
4393 $Mangled .= "v";
4394 }
4395 }
4396 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4397 $Mangled = write_stdcxx_substitution($Mangled);
4398 if($Mangled eq "_Z") {
4399 return "";
4400 }
4401 return $Mangled;
4402}
4403
4404sub correct_incharge($$$)
4405{
4406 my ($InfoId, $LibVersion, $Mangled) = @_;
4407 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4408 {
4409 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004410 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004411 }
4412 }
4413 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4414 {
4415 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004416 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004417 }
4418 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004419 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004420 }
4421 }
4422 return $Mangled;
4423}
4424
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004425sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004426{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004427 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004428 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004429 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004430 return $Name;
4431 }
4432 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004433 while(my $CPos = find_center($TParams, "<"))
4434 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004435 $TParams = substr($TParams, $CPos);
4436 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004437 if($TParams=~s/\A<(.+)>\Z/$1/) {
4438 $Name=~s/<\Q$TParams\E>\Z//;
4439 }
4440 else
4441 { # error
4442 $TParams = "";
4443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004444 return ($Name, $TParams);
4445}
4446
4447sub get_sub_ns($)
4448{
4449 my $Name = $_[0];
4450 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004451 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004452 {
4453 push(@NS, substr($Name, 0, $CPos));
4454 $Name = substr($Name, $CPos);
4455 $Name=~s/\A:://;
4456 }
4457 return (join("::", @NS), $Name);
4458}
4459
4460sub mangle_ns($$$)
4461{
4462 my ($Name, $LibVersion, $Repl) = @_;
4463 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4464 {
4465 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4466 $Mangled=~s/\AN(.+)E\Z/$1/;
4467 return $Mangled;
4468
4469 }
4470 else
4471 {
4472 my ($MangledNS, $SubNS) = ("", "");
4473 ($SubNS, $Name) = get_sub_ns($Name);
4474 if($SubNS) {
4475 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4476 }
4477 $MangledNS .= length($Name).$Name;
4478 add_substitution($MangledNS, $Repl, 0);
4479 return $MangledNS;
4480 }
4481}
4482
4483sub mangle_param($$$)
4484{
4485 my ($PTid, $LibVersion, $Repl) = @_;
4486 my ($MPrefix, $Mangled) = ("", "");
4487 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004488 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004489 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004490 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004491 if(not $BaseType_Name) {
4492 return "";
4493 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004494 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004495 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004496 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4497 while($Suffix=~/(&|\*|const)\Z/)
4498 {
4499 if($Suffix=~s/[ ]*&\Z//) {
4500 $MPrefix .= "R";
4501 }
4502 if($Suffix=~s/[ ]*\*\Z//) {
4503 $MPrefix .= "P";
4504 }
4505 if($Suffix=~s/[ ]*const\Z//)
4506 {
4507 if($MPrefix=~/R|P/
4508 or $Suffix=~/&|\*/) {
4509 $MPrefix .= "K";
4510 }
4511 }
4512 if($Suffix=~s/[ ]*volatile\Z//) {
4513 $MPrefix .= "V";
4514 }
4515 #if($Suffix=~s/[ ]*restrict\Z//) {
4516 #$MPrefix .= "r";
4517 #}
4518 }
4519 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4520 $Mangled .= $Token;
4521 }
4522 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4523 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004524 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004525 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004526 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004527 foreach (@TPos) {
4528 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4529 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004530 }
4531 elsif($TmplParams)
4532 { # remangling mode
4533 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004534 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004535 }
4536 my $MangledNS = "";
4537 my ($SubNS, $SName) = get_sub_ns($ShortName);
4538 if($SubNS) {
4539 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4540 }
4541 $MangledNS .= length($SName).$SName;
4542 if(@TParams) {
4543 add_substitution($MangledNS, $Repl, 0);
4544 }
4545 $Mangled .= "N".$MangledNS;
4546 if(@TParams)
4547 { # templates
4548 $Mangled .= "I";
4549 foreach my $TParam (@TParams) {
4550 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4551 }
4552 $Mangled .= "E";
4553 }
4554 $Mangled .= "E";
4555 }
4556 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4557 {
4558 if($BaseType{"Type"} eq "MethodPtr") {
4559 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4560 }
4561 else {
4562 $Mangled .= "PF";
4563 }
4564 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4565 my @Params = keys(%{$BaseType{"Param"}});
4566 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4567 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4568 }
4569 if(not @Params) {
4570 $Mangled .= "v";
4571 }
4572 $Mangled .= "E";
4573 }
4574 elsif($BaseType{"Type"} eq "FieldPtr")
4575 {
4576 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4577 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4578 }
4579 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4580 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4581 {
4582 if($Mangled eq $Optimized)
4583 {
4584 if($ShortName!~/::/)
4585 { # remove "N ... E"
4586 if($MPrefix) {
4587 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4588 }
4589 else {
4590 $Mangled=~s/\AN(.+)E\Z/$1/g;
4591 }
4592 }
4593 }
4594 else {
4595 $Mangled = $Optimized;
4596 }
4597 }
4598 add_substitution($Mangled, $Repl, 1);
4599 return $Mangled;
4600}
4601
4602sub mangle_template_param($$$)
4603{ # types + literals
4604 my ($TParam, $LibVersion, $Repl) = @_;
4605 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4606 return mangle_param($TPTid, $LibVersion, $Repl);
4607 }
4608 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4609 { # class_name<1u>::method(...)
4610 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4611 }
4612 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4613 { # class_name<(signed char)1>::method(...)
4614 return "L".$IntrinsicMangling{$1}.$2."E";
4615 }
4616 elsif($TParam eq "true")
4617 { # class_name<true>::method(...)
4618 return "Lb1E";
4619 }
4620 elsif($TParam eq "false")
4621 { # class_name<true>::method(...)
4622 return "Lb0E";
4623 }
4624 else { # internal error
4625 return length($TParam).$TParam;
4626 }
4627}
4628
4629sub add_substitution($$$)
4630{
4631 my ($Value, $Repl, $Rec) = @_;
4632 if($Rec)
4633 { # subtypes
4634 my @Subs = ($Value);
4635 while($Value=~s/\A(R|P|K)//) {
4636 push(@Subs, $Value);
4637 }
4638 foreach (reverse(@Subs)) {
4639 add_substitution($_, $Repl, 0);
4640 }
4641 return;
4642 }
4643 return if($Value=~/\AS(\d*)_\Z/);
4644 $Value=~s/\AN(.+)E\Z/$1/g;
4645 return if(defined $Repl->{$Value});
4646 return if(length($Value)<=1);
4647 return if($StdcxxMangling{$Value});
4648 # check for duplicates
4649 my $Base = $Value;
4650 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4651 {
4652 my $Num = $Repl->{$Type};
4653 my $Replace = macro_mangle($Num);
4654 $Base=~s/\Q$Replace\E/$Type/;
4655 }
4656 if(my $OldNum = $Repl->{$Base})
4657 {
4658 $Repl->{$Value} = $OldNum;
4659 return;
4660 }
4661 my @Repls = sort {$b<=>$a} values(%{$Repl});
4662 if(@Repls) {
4663 $Repl->{$Value} = $Repls[0]+1;
4664 }
4665 else {
4666 $Repl->{$Value} = -1;
4667 }
4668 # register duplicates
4669 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004670 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004671 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4672 {
4673 next if($Base eq $Type);
4674 my $Num = $Repl->{$Type};
4675 my $Replace = macro_mangle($Num);
4676 $Base=~s/\Q$Type\E/$Replace/;
4677 $Repl->{$Base} = $Repl->{$Value};
4678 }
4679}
4680
4681sub macro_mangle($)
4682{
4683 my $Num = $_[0];
4684 if($Num==-1) {
4685 return "S_";
4686 }
4687 else
4688 {
4689 my $Code = "";
4690 if($Num<10)
4691 { # S0_, S1_, S2_, ...
4692 $Code = $Num;
4693 }
4694 elsif($Num>=10 and $Num<=35)
4695 { # SA_, SB_, SC_, ...
4696 $Code = chr(55+$Num);
4697 }
4698 else
4699 { # S10_, S11_, S12_
4700 $Code = $Num-26; # 26 is length of english alphabet
4701 }
4702 return "S".$Code."_";
4703 }
4704}
4705
4706sub write_stdcxx_substitution($)
4707{
4708 my $Mangled = $_[0];
4709 if($StdcxxMangling{$Mangled}) {
4710 return $StdcxxMangling{$Mangled};
4711 }
4712 else
4713 {
4714 my @Repls = keys(%StdcxxMangling);
4715 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4716 foreach my $MangledType (@Repls)
4717 {
4718 my $Replace = $StdcxxMangling{$MangledType};
4719 #if($Mangled!~/$Replace/) {
4720 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4721 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4722 #}
4723 }
4724 }
4725 return $Mangled;
4726}
4727
4728sub write_substitution($$)
4729{
4730 my ($Mangled, $Repl) = @_;
4731 if(defined $Repl->{$Mangled}
4732 and my $MnglNum = $Repl->{$Mangled}) {
4733 $Mangled = macro_mangle($MnglNum);
4734 }
4735 else
4736 {
4737 my @Repls = keys(%{$Repl});
4738 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4739 # FIXME: how to apply replacements? by num or by pos
4740 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4741 foreach my $MangledType (@Repls)
4742 {
4743 my $Replace = macro_mangle($Repl->{$MangledType});
4744 if($Mangled!~/$Replace/) {
4745 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4746 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4747 }
4748 }
4749 }
4750 return $Mangled;
4751}
4752
4753sub delete_keywords($)
4754{
4755 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004756 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004757 return $TypeName;
4758}
4759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004760sub uncover_typedefs($$)
4761{
4762 my ($TypeName, $LibVersion) = @_;
4763 return "" if(not $TypeName);
4764 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4765 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4766 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004767 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004768 while($TypeName_New ne $TypeName_Pre)
4769 {
4770 $TypeName_Pre = $TypeName_New;
4771 my $TypeName_Copy = $TypeName_New;
4772 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004773 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004774 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004775 if(not $Intrinsic_Keywords{$1}) {
4776 $Words{$1} = 1;
4777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004778 }
4779 foreach my $Word (keys(%Words))
4780 {
4781 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4782 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004783 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004784 if($BaseType_Name=~/\([\*]+\)/)
4785 { # FuncPtr
4786 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4787 {
4788 my $Type_Suffix = $1;
4789 $TypeName_New = $BaseType_Name;
4790 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004791 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004792 }
4793 }
4794 }
4795 else
4796 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004797 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004798 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004799 }
4800 }
4801 }
4802 }
4803 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4804}
4805
4806sub isInternal($)
4807{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004808 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4809 {
4810 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4811 {
4812 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4813 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4814 return 1;
4815 }
4816 }
4817 }
4818 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004819}
4820
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004821sub getDataVal($$)
4822{
4823 my ($InfoId, $TypeId) = @_;
4824 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4825 {
4826 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4827 {
4828 if(defined $LibInfo{$Version}{"info_type"}{$1}
4829 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004830 {
4831 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004832 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004833 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4834 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004835 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004836 if(my $Addr = getTreeAttr_Op($1)) {
4837 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004838 }
4839 }
4840 }
4841 }
4842 else {
4843 return getInitVal($1, $TypeId);
4844 }
4845 }
4846 }
4847 return undef;
4848}
4849
4850sub getInitVal($$)
4851{
4852 my ($InfoId, $TypeId) = @_;
4853 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4854 {
4855 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4856 {
4857 if($InfoType eq "integer_cst")
4858 {
4859 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004860 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004861 { # characters
4862 $Val = chr($Val);
4863 }
4864 return $Val;
4865 }
4866 elsif($InfoType eq "string_cst") {
4867 return getNodeStrCst($InfoId);
4868 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004869 elsif($InfoType eq "var_decl")
4870 {
4871 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4872 return $Name;
4873 }
4874 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004875 }
4876 }
4877 return undef;
4878}
4879
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004880sub set_Class_And_Namespace($)
4881{
4882 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004883 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004884 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004885 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004886 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004887 my $NSInfoId = $1;
4888 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4889 {
4890 if($InfoType eq "namespace_decl") {
4891 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4892 }
4893 elsif($InfoType eq "record_type") {
4894 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4895 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004897 }
4898 }
4899 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4900 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004901 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004902 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004903 { # skip
4904 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004906 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004907
4908 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004909}
4910
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004911sub debugMangling($)
4912{
4913 my $LibVersion = $_[0];
4914 my %Mangled = ();
4915 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4916 {
4917 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4918 {
4919 if($Mngl=~/\A(_Z|\?)/) {
4920 $Mangled{$Mngl}=$InfoId;
4921 }
4922 }
4923 }
4924 translateSymbols(keys(%Mangled), $LibVersion);
4925 foreach my $Mngl (keys(%Mangled))
4926 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004927 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4928 my $U2 = $tr_name{$Mngl};
4929 if($U1 ne $U2) {
4930 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004931 }
4932 }
4933}
4934
4935sub linkSymbol($)
4936{ # link symbols from shared libraries
4937 # with the symbols from header files
4938 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004939 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004940 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004941 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4942 or $EMERGENCY_MODE_48)
4943 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4944 # 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 +03004945 # GCC 4.8.[012] doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004946 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004947 {
4948 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4949 return correct_incharge($InfoId, $Version, $Mangled);
4950 }
4951 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004952 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004953 or not $BinaryOnly
4954 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004955 { # 1. --headers-only mode
4956 # 2. not mangled src-only symbols
4957 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4958 return $Mangled;
4959 }
4960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004961 }
4962 return "";
4963}
4964
4965sub setLanguage($$)
4966{
4967 my ($LibVersion, $Lang) = @_;
4968 if(not $UserLang) {
4969 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4970 }
4971}
4972
4973sub getSymbolInfo($)
4974{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004975 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004976 if(isInternal($InfoId)) {
4977 return;
4978 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004979 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4980 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004981 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4982 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004983 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004984 return;
4985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004986 setFuncAccess($InfoId);
4987 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004988 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4989 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004990 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004991 return;
4992 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004993
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004994 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004995 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004996 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004997 if(not defined $TypeInfo{$Version}{$Return}
4998 or not $TypeInfo{$Version}{$Return}{"Name"})
4999 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005000 delete($SymbolInfo{$Version}{$InfoId});
5001 return;
5002 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005003 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005004 }
5005 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5006 {
5007 if(defined $MissedTypedef{$Version}{$Rid})
5008 {
5009 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5010 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5011 }
5012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005014 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5015 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005016 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005017 my $Orig = getFuncOrig($InfoId);
5018 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005019 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5020 {
5021 delete($SymbolInfo{$Version}{$InfoId});
5022 return;
5023 }
5024
5025 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005026 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005027 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005028 return;
5029 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005030
5031 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005033 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5034
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005035 my @TParams = getTParams($Orig, "Func");
5036 if(not @TParams)
5037 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005038 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005039 return;
5040 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005041 foreach my $Pos (0 .. $#TParams)
5042 {
5043 my $Val = $TParams[$Pos];
5044 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5045
5046 if($Tmpl)
5047 {
5048 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5049 {
5050 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5051 }
5052 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005053 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005054
5055 if($Tmpl)
5056 {
5057 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5058 {
5059 if($Pos>$#TParams)
5060 {
5061 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5062 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5063 }
5064 }
5065 }
5066
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005067 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5068 { # operator<< <T>, operator>> <T>
5069 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5070 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005071 if(@TParams) {
5072 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5073 }
5074 else {
5075 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5076 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005077 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005078 }
5079 else
5080 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005081 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005082 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005083 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5084 {
5085 if($OSgroup eq "windows")
5086 { # cut the offset
5087 $MnglName=~s/\@\d+\Z//g;
5088 }
5089 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5090
5091 # NOTE: mangling of some symbols may change depending on GCC version
5092 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5093 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5094 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005095
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005096 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005097 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005098 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005099 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005100 return;
5101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005102 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005103 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005104 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005105 if($Skip)
5106 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005107 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005108 return;
5109 }
5110 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005111 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5112 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5113 }
5114
5115 if(set_Class_And_Namespace($InfoId))
5116 {
5117 delete($SymbolInfo{$Version}{$InfoId});
5118 return;
5119 }
5120
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005121 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5122 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005123 if(not defined $TypeInfo{$Version}{$ClassId}
5124 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5125 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005126 delete($SymbolInfo{$Version}{$InfoId});
5127 return;
5128 }
5129 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005130 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5131 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005133 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005135 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005137 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005138 }
5139 if($COMMON_LANGUAGE{$Version} eq "C++")
5140 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005141 # C++ or --headers-only mode
5142 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005143 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005144 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5145 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005147 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005148 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005149 if(my $Mangled = linkSymbol($InfoId)) {
5150 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005151 }
5152 }
5153 if($OStarget eq "windows")
5154 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005155 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005156 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005157 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005158 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005159 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005160 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005161 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005162 }
5163 }
5164 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005165 else
5166 { # not mangled in C
5167 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5168 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005169 if(not $CheckHeadersOnly
5170 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5171 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5172 {
5173 my $Incorrect = 0;
5174
5175 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5176 {
5177 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5178 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5179 { # mangled in the TU dump, but not mangled in the library
5180 $Incorrect = 1;
5181 }
5182 }
5183 else
5184 {
5185 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5186 { # all C++ functions are not mangled in the TU dump
5187 $Incorrect = 1;
5188 }
5189 }
5190 if($Incorrect)
5191 {
5192 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5193 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5194 }
5195 }
5196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005197 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005198 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005199 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005200 return;
5201 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005202 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005203 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005204 { # identify virtual and pure virtual functions
5205 # NOTE: constructors cannot be virtual
5206 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5207 # in the TU dump, so taking it from the original symbol
5208 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5209 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5210 { # NOTE: D2 destructors are not present in a v-table
5211 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005213 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005214 if(isInline($InfoId)) {
5215 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005217 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005218 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005220 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5221 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005222 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005223 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005224 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005225 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005226 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005227 }
5228 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005229 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5230 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005231 if(not $ExtraDump)
5232 {
5233 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5234 { # non-target symbols
5235 delete($SymbolInfo{$Version}{$InfoId});
5236 return;
5237 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005240 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5241 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5242 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5243 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005245 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5246 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005247 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005248 return;
5249 }
5250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005253 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005255 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005256 return;
5257 }
5258 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005260 }
5261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005262 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5263 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5264 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005265 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005266 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5267 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005269 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005270 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005271 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005272 }
5273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005274 if(getFuncLink($InfoId) eq "Static") {
5275 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005277 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5278 {
5279 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5280 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005281 if($Unmangled=~/\.\_\d/)
5282 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005283 delete($SymbolInfo{$Version}{$InfoId});
5284 return;
5285 }
5286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005287 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005288
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005289 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5290 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005291 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005292 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5293 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005295
5296 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5297 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5298 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005299
5300 if($ExtraDump) {
5301 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5302 }
5303}
5304
5305sub guessHeader($)
5306{
5307 my $InfoId = $_[0];
5308 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5309 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5310 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5311 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5312 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5313 {
5314 if(get_filename($HPath) eq $Header)
5315 {
5316 my $HDir = get_filename(get_dirname($HPath));
5317 if($HDir ne "include"
5318 and $HDir=~/\A[a-z]+\Z/i) {
5319 return join_P($HDir, $Header);
5320 }
5321 }
5322 }
5323 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005324}
5325
5326sub isInline($)
5327{ # "body: undefined" in the tree
5328 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005329 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5330 {
5331 if($Info=~/ undefined /i) {
5332 return 0;
5333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005334 }
5335 return 1;
5336}
5337
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005338sub hasThrow($)
5339{
5340 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5341 {
5342 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5343 return getTreeAttr_Unql($1, "unql");
5344 }
5345 }
5346 return 1;
5347}
5348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005349sub getTypeId($)
5350{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005351 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5352 {
5353 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5354 return $1;
5355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005356 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005357 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005358}
5359
5360sub setTypeMemb($$)
5361{
5362 my ($TypeId, $TypeAttr) = @_;
5363 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005364 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005365 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 if($TypeType eq "Enum")
5367 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005368 my $MInfoId = getTreeAttr_Csts($TypeId);
5369 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005370 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005371 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5372 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005373 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005374 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5375 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005376 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005377 }
5378 }
5379 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5380 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005381 my $MInfoId = getTreeAttr_Flds($TypeId);
5382 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005383 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005384 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5385 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005386 if(not $IType or $IType ne "field_decl")
5387 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005388
5389 if($IType eq "var_decl")
5390 { # static field
5391 $StaticFields = 1;
5392 }
5393
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005394 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005395 next;
5396 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005397 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005398 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005399 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005400 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005401 }
5402 if(not $StructMembName)
5403 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005404 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005405 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005406 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005407 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5408 if(isAnon($UnnamedTName))
5409 { # rename unnamed fields to unnamed0, unnamed1, ...
5410 $StructMembName = "unnamed".($UnnamedPos++);
5411 }
5412 }
5413 }
5414 if(not $StructMembName)
5415 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005416 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005417 next;
5418 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005419 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005420 if(defined $MissedTypedef{$Version}{$MembTypeId})
5421 {
5422 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5423 $MembTypeId = $AddedTid;
5424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005425 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005426
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005427 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5428 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005429 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005430 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005431 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5432 }
5433 if($MInfo=~/spec:\s*mutable /)
5434 { # mutable fields
5435 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005436 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005437 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005438 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5439 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005440 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005441 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005442 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443 }
5444 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005445 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005446 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5447 { # template
5448 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5449 }
5450 else {
5451 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005453 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005454
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005455 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005456 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005457 }
5458 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005459
5460 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005461}
5462
5463sub setFuncParams($)
5464{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005465 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005466 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005467
5468 my $FType = getFuncType($InfoId);
5469
5470 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005472 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5473 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005474 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005475 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005476 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5477 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005478 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005479 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5480 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005481 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005482 else
5483 { # skip
5484 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005485 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005486 # skip "this"-parameter
5487 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005488 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005489 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005491 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005492 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5493 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5494 if(not $ParamName)
5495 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005496 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005497 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005498 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5499 {
5500 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5501 $ParamTypeId = $AddedTid;
5502 }
5503 }
5504 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005505 if(not $PType or $PType eq "Unknown") {
5506 return 1;
5507 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005508 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005509 if(not $PTName) {
5510 return 1;
5511 }
5512 if($PTName eq "void") {
5513 last;
5514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005515 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005516 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005518 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005519 $ParamInfoId = getNextElem($ParamInfoId);
5520 next;
5521 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005522 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005523
5524 if(my %Base = get_BaseType($ParamTypeId, $Version))
5525 {
5526 if(defined $Base{"Template"}) {
5527 return 1;
5528 }
5529 }
5530
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005531 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005532 if(my $Algn = getAlgn($ParamInfoId)) {
5533 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5534 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005535 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5536 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005537 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005538 }
5539 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005540 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005541 if($ParamName ne "this" or $FType ne "Method") {
5542 $PPos += 1;
5543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005544 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005545 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005546 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 }
5548 return 0;
5549}
5550
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005551sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005552{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005553 my ($InfoId, $Vtt_Pos) = @_;
5554 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005555 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005556 my $FType = getFuncType($InfoId);
5557
5558 if($FType eq "Method")
5559 {
5560 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005561 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005562 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005563 if(not $ParamListElemId)
5564 { # foo(...)
5565 return 1;
5566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005567 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005568 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005569 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005570 { # actual params: may differ from formal args
5571 # formal int*const
5572 # actual: int*
5573 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005574 {
5575 $Vtt_Pos=-1;
5576 $ParamListElemId = getNextElem($ParamListElemId);
5577 next;
5578 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005579 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5580 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005581 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005582 $HaveVoid = 1;
5583 last;
5584 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005585 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005586 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005587 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5588 {
5589 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5590 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5591 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005592 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005593 }
5594 }
5595 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5596 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005597 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005598 { # params
5599 if($OldId ne $ParamTypeId)
5600 {
5601 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5602 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5603
5604 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5605 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5606 }
5607 }
5608 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005609 }
5610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005611 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005612 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005613 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5614 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005615 if($PurpType eq "nop_expr")
5616 { # func ( const char* arg = (const char*)(void*)0 )
5617 $PurpId = getTreeAttr_Op($PurpId);
5618 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005619 my $Val = getInitVal($PurpId, $ParamTypeId);
5620 if(defined $Val) {
5621 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5622 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623 }
5624 }
5625 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005626 if($Pos!=0 or $FType ne "Method") {
5627 $PPos += 1;
5628 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005629 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005630 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005631 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005632}
5633
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005634sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005635{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005636 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5637 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005638 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5639 return $1;
5640 }
5641 }
5642 return "";
5643}
5644
5645sub getTreeAttr_Chain($)
5646{
5647 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5648 {
5649 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5650 return $1;
5651 }
5652 }
5653 return "";
5654}
5655
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005656sub getTreeAttr_Unql($)
5657{
5658 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5659 {
5660 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5661 return $1;
5662 }
5663 }
5664 return "";
5665}
5666
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005667sub getTreeAttr_Scpe($)
5668{
5669 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5670 {
5671 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5672 return $1;
5673 }
5674 }
5675 return "";
5676}
5677
5678sub getTreeAttr_Type($)
5679{
5680 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5681 {
5682 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5683 return $1;
5684 }
5685 }
5686 return "";
5687}
5688
5689sub getTreeAttr_Name($)
5690{
5691 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5692 {
5693 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5694 return $1;
5695 }
5696 }
5697 return "";
5698}
5699
5700sub getTreeAttr_Mngl($)
5701{
5702 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5703 {
5704 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5705 return $1;
5706 }
5707 }
5708 return "";
5709}
5710
5711sub getTreeAttr_Prms($)
5712{
5713 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5714 {
5715 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5716 return $1;
5717 }
5718 }
5719 return "";
5720}
5721
5722sub getTreeAttr_Fncs($)
5723{
5724 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5725 {
5726 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5727 return $1;
5728 }
5729 }
5730 return "";
5731}
5732
5733sub getTreeAttr_Csts($)
5734{
5735 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5736 {
5737 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5738 return $1;
5739 }
5740 }
5741 return "";
5742}
5743
5744sub getTreeAttr_Purp($)
5745{
5746 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5747 {
5748 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5749 return $1;
5750 }
5751 }
5752 return "";
5753}
5754
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005755sub getTreeAttr_Op($)
5756{
5757 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5758 {
5759 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5760 return $1;
5761 }
5762 }
5763 return "";
5764}
5765
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005766sub getTreeAttr_Valu($)
5767{
5768 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5769 {
5770 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5771 return $1;
5772 }
5773 }
5774 return "";
5775}
5776
5777sub getTreeAttr_Flds($)
5778{
5779 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5780 {
5781 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5782 return $1;
5783 }
5784 }
5785 return "";
5786}
5787
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005788sub getTreeAttr_Binf($)
5789{
5790 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5791 {
5792 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5793 return $1;
5794 }
5795 }
5796 return "";
5797}
5798
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005799sub getTreeAttr_Args($)
5800{
5801 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5802 {
5803 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005804 return $1;
5805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005806 }
5807 return "";
5808}
5809
5810sub getTreeValue($)
5811{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005812 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5813 {
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +03005814 if($Info=~/(low|int)[ ]*:[ ]*([^ ]+) /) {
5815 return $2;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005817 }
5818 return "";
5819}
5820
5821sub getTreeAccess($)
5822{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005823 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005824 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005825 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5826 {
5827 my $Access = $1;
5828 if($Access eq "prot") {
5829 return "protected";
5830 }
5831 elsif($Access eq "priv") {
5832 return "private";
5833 }
5834 }
5835 elsif($Info=~/ protected /)
5836 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005837 return "protected";
5838 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005839 elsif($Info=~/ private /)
5840 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005841 return "private";
5842 }
5843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005844 return "public";
5845}
5846
5847sub setFuncAccess($)
5848{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005849 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005850 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005851 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005852 }
5853 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005854 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005855 }
5856}
5857
5858sub setTypeAccess($$)
5859{
5860 my ($TypeId, $TypeAttr) = @_;
5861 my $Access = getTreeAccess($TypeId);
5862 if($Access eq "protected") {
5863 $TypeAttr->{"Protected"} = 1;
5864 }
5865 elsif($Access eq "private") {
5866 $TypeAttr->{"Private"} = 1;
5867 }
5868}
5869
5870sub setFuncKind($)
5871{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005872 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5873 {
5874 if($Info=~/pseudo tmpl/) {
5875 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5876 }
5877 elsif($Info=~/ constructor /) {
5878 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5879 }
5880 elsif($Info=~/ destructor /) {
5881 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005883 }
5884}
5885
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005886sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005888 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5889 {
5890 if($Info=~/spec[ ]*:[ ]*pure /) {
5891 return "PureVirt";
5892 }
5893 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5894 return "Virt";
5895 }
5896 elsif($Info=~/ pure\s+virtual /)
5897 { # support for old GCC versions
5898 return "PureVirt";
5899 }
5900 elsif($Info=~/ virtual /)
5901 { # support for old GCC versions
5902 return "Virt";
5903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005904 }
5905 return "";
5906}
5907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005908sub getFuncLink($)
5909{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005910 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5911 {
5912 if($Info=~/link[ ]*:[ ]*static /) {
5913 return "Static";
5914 }
5915 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005916 return $1;
5917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005918 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005919 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005920}
5921
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005922sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005923{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005924 my ($Symbol, $LibVersion) = @_;
5925 return "" if(not $Symbol or not $LibVersion);
5926 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5927 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005929 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5930 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5931 }
5932 }
5933 if($NS)
5934 {
5935 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5936 return $NS;
5937 }
5938 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005939 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005940 while($NS=~s/::[^:]+\Z//)
5941 {
5942 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5943 return $NS;
5944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005945 }
5946 }
5947 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005948
5949 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005950}
5951
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005952sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005953{
5954 my ($TypeName, $LibVersion) = @_;
5955 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005956 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005958 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5959 return $NS;
5960 }
5961 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005963 while($NS=~s/::[^:]+\Z//)
5964 {
5965 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5966 return $NS;
5967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005968 }
5969 }
5970 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005971 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005972}
5973
5974sub getNameSpace($)
5975{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005976 my $InfoId = $_[0];
5977 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005979 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005980 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005981 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005982 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005983 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5984 {
5985 my $NameSpace = getTreeStr($1);
5986 if($NameSpace eq "::")
5987 { # global namespace
5988 return "";
5989 }
5990 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5991 $NameSpace = $BaseNameSpace."::".$NameSpace;
5992 }
5993 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5994 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005995 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005996 else {
5997 return "";
5998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005999 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006000 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006001 { # inside data type
6002 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6003 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006004 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006006 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006007 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008}
6009
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010sub getEnumMembVal($)
6011{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006012 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006013 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006014 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6015 {
6016 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6017 {
6018 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6019 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6020 return getTreeValue($1);
6021 }
6022 else
6023 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6024 return getTreeValue($1);
6025 }
6026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006027 }
6028 }
6029 return "";
6030}
6031
6032sub getSize($)
6033{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006034 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6035 {
6036 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6037 return getTreeValue($1);
6038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006039 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006040 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006041}
6042
6043sub getAlgn($)
6044{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006045 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6046 {
6047 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6048 return $1;
6049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006051 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006052}
6053
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006054sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6057 {
6058 if($Info=~/ bitfield /) {
6059 return getSize($_[0]);
6060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006062 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063}
6064
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006065sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006067 if(my $Chan = getTreeAttr_Chan($_[0])) {
6068 return $Chan;
6069 }
6070 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6071 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006073 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074}
6075
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006076sub registerHeader($$)
6077{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006078 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006079 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006080 return "";
6081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006082 if(is_abs($Header) and not -f $Header)
6083 { # incorrect absolute path
6084 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006086 if(skipHeader($Header, $LibVersion))
6087 { # skip
6088 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006089 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006090 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6091 {
6092 detect_header_includes($Header_Path, $LibVersion);
6093
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006094 if(defined $Tolerance and $Tolerance=~/3/)
6095 { # 3 - skip headers that include non-Linux headers
6096 if($OSgroup ne "windows")
6097 {
6098 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6099 {
6100 if(specificHeader($Inc, "windows")) {
6101 return "";
6102 }
6103 }
6104 }
6105 }
6106
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006107 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6108 { # redirect
6109 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6110 or skipHeader($RHeader_Path, $LibVersion))
6111 { # skip
6112 return "";
6113 }
6114 $Header_Path = $RHeader_Path;
6115 }
6116 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6117 { # skip
6118 return "";
6119 }
6120
6121 if(my $HName = get_filename($Header_Path))
6122 { # register
6123 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6124 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6125 }
6126
6127 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6128 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006129 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006130 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006131 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006132 }
6133
6134 if($CheckHeadersOnly
6135 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6136 { # /usr/include/c++/4.6.1/...
6137 $STDCXX_TESTING = 1;
6138 }
6139
6140 return $Header_Path;
6141 }
6142 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006143}
6144
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006145sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006146{
6147 my ($Dir, $WithDeps, $LibVersion) = @_;
6148 $Dir=~s/[\/\\]+\Z//g;
6149 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006150 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006151
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006153 if($WithDeps)
6154 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006155 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6156 return;
6157 }
6158 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6159 $Mode = "DepsOnly";
6160 }
6161 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006162 else
6163 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6165 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6166 return;
6167 }
6168 }
6169 $Header_Dependency{$LibVersion}{$Dir} = 1;
6170 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6171 if($Mode eq "DepsOnly")
6172 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006173 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006174 $Header_Dependency{$LibVersion}{$Path} = 1;
6175 }
6176 return;
6177 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006178 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006179 {
6180 if($WithDeps)
6181 {
6182 my $SubDir = $Path;
6183 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6184 { # register all sub directories
6185 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6186 }
6187 }
6188 next if(is_not_header($Path));
6189 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006190 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006191 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6193 }
6194 }
6195 if(get_filename($Dir) eq "include")
6196 { # search for "lib/include/" directory
6197 my $LibDir = $Dir;
6198 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006199 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006200 }
6201 }
6202}
6203
6204sub parse_redirect($$$)
6205{
6206 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006207 my @Errors = ();
6208 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6209 push(@Errors, $1);
6210 }
6211 my $Redirect = "";
6212 foreach (@Errors)
6213 {
6214 s/\s{2,}/ /g;
6215 if(/(only|must\ include
6216 |update\ to\ include
6217 |replaced\ with
6218 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006219 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 {
6221 $Redirect = $2;
6222 last;
6223 }
6224 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6225 {
6226 $Redirect = $2;
6227 last;
6228 }
6229 elsif(/this\ header\ should\ not\ be\ used
6230 |programs\ should\ not\ directly\ include
6231 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6232 |is\ not\ supported\ API\ for\ general\ use
6233 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006234 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006235 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6236 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6237 }
6238 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006239 if($Redirect)
6240 {
6241 $Redirect=~s/\A<//g;
6242 $Redirect=~s/>\Z//g;
6243 }
6244 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006245}
6246
6247sub parse_includes($$)
6248{
6249 my ($Content, $Path) = @_;
6250 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006251 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006252 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006253 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006254 my $Method = substr($Header, 0, 1, "");
6255 substr($Header, length($Header)-1, 1, "");
6256 $Header = path_format($Header, $OSgroup);
6257 if($Method eq "\"" or is_abs($Header))
6258 {
6259 if(-e join_P(get_dirname($Path), $Header))
6260 { # relative path exists
6261 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006262 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006263 else
6264 { # include "..." that doesn't exist is equal to include <...>
6265 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006266 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006267 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006268 else {
6269 $Includes{$Header} = 1;
6270 }
6271 }
6272 if($ExtraInfo)
6273 {
6274 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6275 { # FT_FREETYPE_H
6276 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006277 }
6278 }
6279 return \%Includes;
6280}
6281
6282sub ignore_path($)
6283{
6284 my $Path = $_[0];
6285 if($Path=~/\~\Z/)
6286 {# skipping system backup files
6287 return 1;
6288 }
6289 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6290 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6291 return 1;
6292 }
6293 return 0;
6294}
6295
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006296sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006297{
6298 my ($ArrRef, $W) = @_;
6299 return if(length($W)<2);
6300 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6301}
6302
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006303sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006304{
6305 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006307 $H1=~s/\.[a-z]+\Z//ig;
6308 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006309
6310 my $Hname1 = get_filename($H1);
6311 my $Hname2 = get_filename($H2);
6312 my $HDir1 = get_dirname($H1);
6313 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006314 my $Dirname1 = get_filename($HDir1);
6315 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006316
6317 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6318 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6319
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006320 if($_[0] eq $_[1]
6321 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 return 0;
6323 }
6324 elsif($H1=~/\A\Q$H2\E/) {
6325 return 1;
6326 }
6327 elsif($H2=~/\A\Q$H1\E/) {
6328 return -1;
6329 }
6330 elsif($HDir1=~/\Q$Hname1\E/i
6331 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006332 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006333 return -1;
6334 }
6335 elsif($HDir2=~/\Q$Hname2\E/i
6336 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 return 1;
6339 }
6340 elsif($Hname1=~/\Q$Dirname1\E/i
6341 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006342 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 return -1;
6344 }
6345 elsif($Hname2=~/\Q$Dirname2\E/i
6346 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006347 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006348 return 1;
6349 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006350 elsif($Hname1=~/(config|lib|util)/i
6351 and $Hname2!~/(config|lib|util)/i)
6352 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 return -1;
6354 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006355 elsif($Hname2=~/(config|lib|util)/i
6356 and $Hname1!~/(config|lib|util)/i)
6357 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006358 return 1;
6359 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006360 else
6361 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006362 my $R1 = checkRelevance($H1);
6363 my $R2 = checkRelevance($H2);
6364 if($R1 and not $R2)
6365 { # libebook/e-book.h
6366 return -1;
6367 }
6368 elsif($R2 and not $R1)
6369 { # libebook/e-book.h
6370 return 1;
6371 }
6372 else
6373 {
6374 return (lc($H1) cmp lc($H2));
6375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006376 }
6377}
6378
6379sub searchForHeaders($)
6380{
6381 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006382
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006383 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006384 registerGccHeaders();
6385
6386 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6387 { # c++ standard include paths
6388 registerCppHeaders();
6389 }
6390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006392 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6393 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006394 {
6395 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006396 if($SystemRoot)
6397 {
6398 if(is_abs($Path)) {
6399 $Path = $SystemRoot.$Path;
6400 }
6401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006402 if(not -e $Path) {
6403 exitStatus("Access_Error", "can't access \'$Path\'");
6404 }
6405 elsif(-f $Path) {
6406 exitStatus("Access_Error", "\'$Path\' - not a directory");
6407 }
6408 elsif(-d $Path)
6409 {
6410 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006411 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006412 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6413 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006414 }
6415 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006416 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006417 }
6418 }
6419 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006420 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006421 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6422 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006423
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006424 # registering directories
6425 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6426 {
6427 next if(not -e $Path);
6428 $Path = get_abs_path($Path);
6429 $Path = path_format($Path, $OSgroup);
6430 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006431 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006432 }
6433 elsif(-f $Path)
6434 {
6435 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006436 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 and not $LocalIncludes{$Dir})
6438 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006439 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006440 # if(my $OutDir = get_dirname($Dir))
6441 # { # registering the outer directory
6442 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6443 # and not $LocalIncludes{$OutDir}) {
6444 # registerDir($OutDir, 0, $LibVersion);
6445 # }
6446 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006447 }
6448 }
6449 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006450
6451 # clean memory
6452 %RegisteredDirs = ();
6453
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006454 # registering headers
6455 my $Position = 0;
6456 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6457 {
6458 if(is_abs($Dest) and not -e $Dest) {
6459 exitStatus("Access_Error", "can't access \'$Dest\'");
6460 }
6461 $Dest = path_format($Dest, $OSgroup);
6462 if(is_header($Dest, 1, $LibVersion))
6463 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006464 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006465 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6466 }
6467 }
6468 elsif(-d $Dest)
6469 {
6470 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006471 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006472 {
6473 next if(ignore_path($Path));
6474 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006475 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006476 push(@Registered, $HPath);
6477 }
6478 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006479 @Registered = sort {sortHeaders($a, $b)} @Registered;
6480 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006481 foreach my $Path (@Registered) {
6482 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6483 }
6484 }
6485 else {
6486 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6487 }
6488 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006489
6490 if(defined $Tolerance and $Tolerance=~/4/)
6491 { # 4 - skip headers included by others
6492 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6493 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006494 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006495 delete($Registered_Headers{$LibVersion}{$Path});
6496 }
6497 }
6498 }
6499
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006500 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6501 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006502 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006503 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006504 if(is_abs($Header) and not -f $Header) {
6505 exitStatus("Access_Error", "can't access file \'$Header\'");
6506 }
6507 $Header = path_format($Header, $OSgroup);
6508 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006510 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006511 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006512 }
6513 else {
6514 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006516 }
6517 }
6518 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6519 { # set relative paths (for duplicates)
6520 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6521 { # search for duplicates
6522 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6523 my $Prefix = get_dirname($FirstPath);
6524 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6525 { # detect a shortest distinguishing prefix
6526 my $NewPrefix = $1;
6527 my %Identity = ();
6528 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6529 {
6530 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6531 $Identity{$Path} = $1;
6532 }
6533 }
6534 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006535 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006536 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6537 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6538 }
6539 last;
6540 }
6541 $Prefix = $NewPrefix; # increase prefix
6542 }
6543 }
6544 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006545
6546 # clean memory
6547 %HeaderName_Paths = ();
6548
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006549 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6550 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006551 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006552 my ($Pos, $PairPos) = (-1, -1);
6553 my ($Path, $PairPath) = ();
6554 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6555 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6556 foreach my $Header_Path (@Paths)
6557 {
6558 if(get_filename($Header_Path) eq $PairName)
6559 {
6560 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6561 $PairPath = $Header_Path;
6562 }
6563 if(get_filename($Header_Path) eq $HeaderName)
6564 {
6565 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6566 $Path = $Header_Path;
6567 }
6568 }
6569 if($PairPos!=-1 and $Pos!=-1
6570 and int($PairPos)<int($Pos))
6571 {
6572 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6573 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6574 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6575 }
6576 }
6577 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6578 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6579 }
6580}
6581
6582sub detect_real_includes($$)
6583{
6584 my ($AbsPath, $LibVersion) = @_;
6585 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6586 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6587 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6588 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6589 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006590 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006592 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6593 return () if(not $Path);
6594 open(PREPROC, $Path);
6595 while(<PREPROC>)
6596 {
6597 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6598 {
6599 my $Include = path_format($1, $OSgroup);
6600 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6601 next;
6602 }
6603 if($Include eq $AbsPath) {
6604 next;
6605 }
6606 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6607 }
6608 }
6609 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006610 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6611}
6612
6613sub detect_header_includes($$)
6614{
6615 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006616 return if(not $LibVersion or not $Path);
6617 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6618 return;
6619 }
6620 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6621
6622 if(not -e $Path) {
6623 return;
6624 }
6625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006626 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006627 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6628 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006629 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006630 {
6631 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006632 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006633 }
6634 if($RedirectPath ne $Path) {
6635 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6636 }
6637 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006638 else
6639 { # can't find
6640 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006642 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006643 if(my $Inc = parse_includes($Content, $Path))
6644 {
6645 foreach my $Include (keys(%{$Inc}))
6646 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006647 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006648
6649 if(defined $Tolerance and $Tolerance=~/4/)
6650 {
6651 if(my $HPath = identifyHeader($Include, $LibVersion))
6652 {
6653 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6654 }
6655 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006658}
6659
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006660sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006661{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 my $Path = $_[0];
6663 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006664 if($OStarget eq "symbian")
6665 {
6666 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6667 { # epoc32/include/libc/{stdio, ...}.h
6668 return 1;
6669 }
6670 }
6671 else
6672 {
6673 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6674 { # /usr/include/{stdio, ...}.h
6675 return 1;
6676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006677 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006678 return 0;
6679}
6680
6681sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006682{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006683 my $Dir = $_[0];
6684 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006685 if($OStarget eq "symbian")
6686 {
6687 if(get_filename($OutDir) eq "libc"
6688 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6689 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6690 return 1;
6691 }
6692 }
6693 else
6694 { # linux
6695 if($OutDir eq "/usr/include"
6696 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6697 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6698 return 1;
6699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006700 }
6701 return 0;
6702}
6703
6704sub detect_recursive_includes($$)
6705{
6706 my ($AbsPath, $LibVersion) = @_;
6707 return () if(not $AbsPath);
6708 if(isCyclical(\@RecurInclude, $AbsPath)) {
6709 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6710 }
6711 my ($AbsDir, $Name) = separate_path($AbsPath);
6712 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006713 { # system GLIBC internals
6714 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006715 }
6716 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6717 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6718 }
6719 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006720
6721 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6722 { # skip /usr/include/c++/*/ headers
6723 return () if(not $ExtraInfo);
6724 }
6725
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006726 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006727 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006728 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 { # check "real" (non-"model") include paths
6730 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6731 pop(@RecurInclude);
6732 return @Paths;
6733 }
6734 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6735 detect_header_includes($AbsPath, $LibVersion);
6736 }
6737 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6738 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006739 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006740 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006741 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006743 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006744 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006745 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006746 }
6747 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006748 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006749 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006750 { # search for the nearest header
6751 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006752 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006753 if(-f $Candidate) {
6754 $HPath = $Candidate;
6755 }
6756 }
6757 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006758 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006759 }
6760 next if(not $HPath);
6761 if($HPath eq $AbsPath) {
6762 next;
6763 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006764
6765 if($Debug)
6766 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006767# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6768# {
6769# print STDERR "$AbsPath -> $HPath\n";
6770# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006771 }
6772
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006773 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6774 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006775 { # only include <...>, skip include "..." prefixes
6776 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6777 }
6778 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6779 {
6780 if($IncPath eq $AbsPath) {
6781 next;
6782 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006783 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6784 if($RIncType==-1)
6785 { # include "..."
6786 $RIncType = $IncType;
6787 }
6788 elsif($RIncType==2)
6789 {
6790 if($IncType!=-1) {
6791 $RIncType = $IncType;
6792 }
6793 }
6794 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6796 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6797 }
6798 }
6799 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6800 {
6801 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6802 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6803 { # distinguish math.h from glibc and math.h from the tested library
6804 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6805 last;
6806 }
6807 }
6808 }
6809 pop(@RecurInclude);
6810 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6811}
6812
6813sub find_in_framework($$$)
6814{
6815 my ($Header, $Framework, $LibVersion) = @_;
6816 return "" if(not $Header or not $Framework or not $LibVersion);
6817 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6818 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6819 }
6820 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6821 {
6822 if(get_filename($Dependency) eq $Framework
6823 and -f get_dirname($Dependency)."/".$Header) {
6824 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6825 }
6826 }
6827 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6828}
6829
6830sub find_in_defaults($)
6831{
6832 my $Header = $_[0];
6833 return "" if(not $Header);
6834 if(defined $Cache{"find_in_defaults"}{$Header}) {
6835 return $Cache{"find_in_defaults"}{$Header};
6836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006837 foreach my $Dir (@DefaultIncPaths,
6838 @DefaultGccPaths,
6839 @DefaultCppPaths,
6840 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006841 {
6842 next if(not $Dir);
6843 if(-f $Dir."/".$Header) {
6844 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6845 }
6846 }
6847 return ($Cache{"find_in_defaults"}{$Header}="");
6848}
6849
6850sub cmp_paths($$)
6851{
6852 my ($Path1, $Path2) = @_;
6853 my @Parts1 = split(/[\/\\]/, $Path1);
6854 my @Parts2 = split(/[\/\\]/, $Path2);
6855 foreach my $Num (0 .. $#Parts1)
6856 {
6857 my $Part1 = $Parts1[$Num];
6858 my $Part2 = $Parts2[$Num];
6859 if($GlibcDir{$Part1}
6860 and not $GlibcDir{$Part2}) {
6861 return 1;
6862 }
6863 elsif($GlibcDir{$Part2}
6864 and not $GlibcDir{$Part1}) {
6865 return -1;
6866 }
6867 elsif($Part1=~/glib/
6868 and $Part2!~/glib/) {
6869 return 1;
6870 }
6871 elsif($Part1!~/glib/
6872 and $Part2=~/glib/) {
6873 return -1;
6874 }
6875 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6876 return $CmpRes;
6877 }
6878 }
6879 return 0;
6880}
6881
6882sub checkRelevance($)
6883{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006884 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006885 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006886
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006887 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006888 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006889 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006890
6891 my $Name = lc(get_filename($Path));
6892 my $Dir = lc(get_dirname($Path));
6893
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006894 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006895
6896 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006897 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006898 my $Len = length($Token);
6899 next if($Len<=1);
6900 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6901 { # include/evolution-data-server-1.4/libebook/e-book.h
6902 return 1;
6903 }
6904 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006905 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006906 return 1;
6907 }
6908 }
6909 return 0;
6910}
6911
6912sub checkFamily(@)
6913{
6914 my @Paths = @_;
6915 return 1 if($#Paths<=0);
6916 my %Prefix = ();
6917 foreach my $Path (@Paths)
6918 {
6919 if($SystemRoot) {
6920 $Path = cut_path_prefix($Path, $SystemRoot);
6921 }
6922 if(my $Dir = get_dirname($Path))
6923 {
6924 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6925 $Prefix{$Dir} += 1;
6926 $Prefix{get_dirname($Dir)} += 1;
6927 }
6928 }
6929 foreach (sort keys(%Prefix))
6930 {
6931 if(get_depth($_)>=3
6932 and $Prefix{$_}==$#Paths+1) {
6933 return 1;
6934 }
6935 }
6936 return 0;
6937}
6938
6939sub isAcceptable($$$)
6940{
6941 my ($Header, $Candidate, $LibVersion) = @_;
6942 my $HName = get_filename($Header);
6943 if(get_dirname($Header))
6944 { # with prefix
6945 return 1;
6946 }
6947 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6948 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6949 return 1;
6950 }
6951 if(checkRelevance($Candidate))
6952 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6953 return 1;
6954 }
6955 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6956 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6957 # /usr/include/qt4/Qt/qsslconfiguration.h
6958 return 1;
6959 }
6960 if($OStarget eq "symbian")
6961 {
6962 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6963 return 1;
6964 }
6965 }
6966 return 0;
6967}
6968
6969sub isRelevant($$$)
6970{ # disallow to search for "abstract" headers in too deep directories
6971 my ($Header, $Candidate, $LibVersion) = @_;
6972 my $HName = get_filename($Header);
6973 if($OStarget eq "symbian")
6974 {
6975 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6976 return 0;
6977 }
6978 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006979 if($OStarget ne "bsd")
6980 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006981 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6982 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6983 return 0;
6984 }
6985 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006986 if($OStarget ne "windows")
6987 {
6988 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6989 { # skip /usr/include/wine/msvcrt
6990 return 0;
6991 }
6992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006993 if(not get_dirname($Header)
6994 and $Candidate=~/[\/\\]wx[\/\\]/)
6995 { # do NOT search in system /wx/ directory
6996 # for headers without a prefix: sstream.h
6997 return 0;
6998 }
6999 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7000 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7001 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7002 return 0;
7003 }
7004 if($Candidate=~/[\/\\]asm-/
7005 and (my $Arch = getArch($LibVersion)) ne "unknown")
7006 { # arch-specific header files
7007 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7008 {# skip ../asm-arm/ if using x86 architecture
7009 return 0;
7010 }
7011 }
7012 my @Candidates = getSystemHeaders($HName, $LibVersion);
7013 if($#Candidates==1)
7014 { # unique header
7015 return 1;
7016 }
7017 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7018 if($#SCandidates==1)
7019 { # unique name
7020 return 1;
7021 }
7022 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7023 if(get_depth($Candidate)-$SystemDepth>=5)
7024 { # abstract headers in too deep directories
7025 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7026 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7027 return 0;
7028 }
7029 }
7030 if($Header eq "parser.h"
7031 and $Candidate!~/\/libxml2\//)
7032 { # select parser.h from xml2 library
7033 return 0;
7034 }
7035 if(not get_dirname($Header)
7036 and keys(%{$SystemHeaders{$HName}})>=3)
7037 { # many headers with the same name
7038 # like thread.h included without a prefix
7039 if(not checkFamily(@Candidates)) {
7040 return 0;
7041 }
7042 }
7043 return 1;
7044}
7045
7046sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007047{ # cache function
7048 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7049 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7050 }
7051 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7052}
7053
7054sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007055{
7056 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007057 if(-f $Header) {
7058 return $Header;
7059 }
7060 if(is_abs($Header) and not -f $Header)
7061 { # incorrect absolute path
7062 return "";
7063 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007064 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007065 { # too abstract configuration headers
7066 return "";
7067 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007068 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007069 if($OSgroup ne "windows")
7070 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007071 if(defined $WinHeaders{lc($HName)}
7072 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007073 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007074 return "";
7075 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007076 }
7077 if($OSgroup ne "macos")
7078 {
7079 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007080 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007081 return "";
7082 }
7083 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007084
7085 if(defined $ObsoleteHeaders{$HName})
7086 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007087 return "";
7088 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007089 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7090 {
7091 if(defined $AlienHeaders{$HName}
7092 or defined $AlienHeaders{$Header})
7093 { # alien headers from other systems
7094 return "";
7095 }
7096 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007097
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007098 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007099 { # search in default paths
7100 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007101 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007102 }
7103 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007104 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007105 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007106 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007107 }
7108 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7109 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7110 {
7111 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007112 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007113 }
7114 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007115 # error
7116 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007117}
7118
7119sub getSystemHeaders($$)
7120{
7121 my ($Header, $LibVersion) = @_;
7122 my @Candidates = ();
7123 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007125 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007126 next;
7127 }
7128 push(@Candidates, $Candidate);
7129 }
7130 return @Candidates;
7131}
7132
7133sub cut_path_prefix($$)
7134{
7135 my ($Path, $Prefix) = @_;
7136 return $Path if(not $Prefix);
7137 $Prefix=~s/[\/\\]+\Z//;
7138 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7139 return $Path;
7140}
7141
7142sub is_default_include_dir($)
7143{
7144 my $Dir = $_[0];
7145 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007146 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007147}
7148
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007149sub identifyHeader($$)
7150{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007151 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007152 if(not $Header) {
7153 return "";
7154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007156 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7157 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007158 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007159 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007160}
7161
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007162sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163{ # search for header by absolute path, relative path or name
7164 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007165 if(-f $Header)
7166 { # it's relative or absolute path
7167 return get_abs_path($Header);
7168 }
7169 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7170 and my $HeaderDir = find_in_defaults($Header))
7171 { # search for libc headers in the /usr/include
7172 # for non-libc target library before searching
7173 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007174 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007175 }
7176 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7177 { # search in the target library paths
7178 return $Path;
7179 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007180 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007181 { # search in the internal GCC include paths
7182 return $DefaultGccHeader{$Header};
7183 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007184 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007186 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007187 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007188 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007189 { # search in the default G++ include paths
7190 return $DefaultCppHeader{$Header};
7191 }
7192 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7193 { # search everywhere in the system
7194 return $AnyPath;
7195 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007196 elsif($OSgroup eq "macos")
7197 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7198 if(my $Dir = get_dirname($Header))
7199 {
7200 my $RelPath = "Headers\/".get_filename($Header);
7201 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007202 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007203 }
7204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007206 # cannot find anything
7207 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007208}
7209
7210sub getLocation($)
7211{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007212 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7213 {
7214 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007215 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007218 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007219}
7220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221sub getNameByInfo($)
7222{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007223 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007224 {
7225 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7226 {
7227 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7228 {
7229 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7230 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007231 my $Str = $1;
7232 if($CppMode{$Version}
7233 and $Str=~/\Ac99_(.+)\Z/)
7234 {
7235 if($CppKeywords_A{$1}) {
7236 $Str=$1;
7237 }
7238 }
7239 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007240 }
7241 }
7242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007243 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007244 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007245}
7246
7247sub getTreeStr($)
7248{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007249 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007251 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7252 {
7253 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007254 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007255 and $Str=~/\Ac99_(.+)\Z/)
7256 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007257 if($CppKeywords_A{$1}) {
7258 $Str=$1;
7259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007260 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007261 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007264 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007267sub getFuncShortName($)
7268{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007269 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007270 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007271 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007272 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007273 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007274 {
7275 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7276 {
7277 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7278 return "operator ".$RName;
7279 }
7280 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007281 }
7282 else
7283 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007284 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7285 {
7286 if(my $Ind = $Operator_Indication{$1}) {
7287 return "operator".$Ind;
7288 }
7289 elsif(not $UnknownOperator{$1})
7290 {
7291 printMsg("WARNING", "unknown operator $1");
7292 $UnknownOperator{$1} = 1;
7293 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007294 }
7295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007296 }
7297 else
7298 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007299 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7300 return getTreeStr($1);
7301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302 }
7303 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007304 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007305}
7306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307sub getFuncReturn($)
7308{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007309 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7310 {
7311 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7312 {
7313 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7314 return $1;
7315 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007316 }
7317 }
7318 return "";
7319}
7320
7321sub getFuncOrig($)
7322{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007323 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7324 {
7325 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7326 return $1;
7327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007328 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007329 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007330}
7331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007332sub unmangleArray(@)
7333{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007334 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007335 { # MSVC mangling
7336 my $UndNameCmd = get_CmdPath("undname");
7337 if(not $UndNameCmd) {
7338 exitStatus("Not_Found", "can't find \"undname\"");
7339 }
7340 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007341 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007342 }
7343 else
7344 { # GCC mangling
7345 my $CppFiltCmd = get_CmdPath("c++filt");
7346 if(not $CppFiltCmd) {
7347 exitStatus("Not_Found", "can't find c++filt in PATH");
7348 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007349 if(not defined $CPPFILT_SUPPORT_FILE)
7350 {
7351 my $Info = `$CppFiltCmd -h 2>&1`;
7352 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7353 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007354 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007355 if($CPPFILT_SUPPORT_FILE)
7356 { # new versions of c++filt can take a file
7357 if($#_>$MAX_CPPFILT_FILE_SIZE)
7358 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7359 # this is fixed in the oncoming version of Binutils
7360 my @Half = splice(@_, 0, ($#_+1)/2);
7361 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007363 else
7364 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007365 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7366 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7367 if($?==139)
7368 { # segmentation fault
7369 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7370 }
7371 return split(/\n/, $Res);
7372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373 }
7374 else
7375 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007376 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7377 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378 my @Half = splice(@_, 0, ($#_+1)/2);
7379 return (unmangleArray(@Half), unmangleArray(@_))
7380 }
7381 else
7382 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007383 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007384 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7385 if($?==139)
7386 { # segmentation fault
7387 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7388 }
7389 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 }
7391 }
7392 }
7393}
7394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007395sub get_ChargeLevel($$)
7396{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007397 my ($Symbol, $LibVersion) = @_;
7398 return "" if($Symbol!~/\A(_Z|\?)/);
7399 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7400 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007402 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007403 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007404 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405 return "[in-charge]";
7406 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007407 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007408 return "[not-in-charge]";
7409 }
7410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007411 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007412 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007413 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007414 return "[in-charge]";
7415 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007416 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007417 return "[not-in-charge]";
7418 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007419 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007420 return "[in-charge-deleting]";
7421 }
7422 }
7423 }
7424 else
7425 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007426 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007427 return "[in-charge]";
7428 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007429 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430 return "[not-in-charge]";
7431 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007432 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007433 return "[in-charge]";
7434 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007435 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436 return "[not-in-charge]";
7437 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007438 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007439 return "[in-charge-deleting]";
7440 }
7441 }
7442 return "";
7443}
7444
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007445sub get_Signature_M($$)
7446{
7447 my ($Symbol, $LibVersion) = @_;
7448 my $Signature_M = $tr_name{$Symbol};
7449 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7450 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007451 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007452 }
7453 return $Signature_M;
7454}
7455
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007456sub get_Signature($$)
7457{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007458 my ($Symbol, $LibVersion) = @_;
7459 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7460 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007462 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007463 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007464
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007465 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007466
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007467 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007469 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7470 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007471 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7472 $ClassName=~s/\bstruct //g;
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007473
7474 if(index($Symbol, "_ZTV")==0) {
7475 return "vtable for $ClassName [data]";
7476 }
7477
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007478 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007479 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7480 $Signature .= "~";
7481 }
7482 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007483 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007484 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007485 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007486 }
7487 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007488 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007490 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7491 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007492 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007493 else
7494 {
7495 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007496 }
7497 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007498 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007500 if($Pos eq "") {
7501 next;
7502 }
7503
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007504 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03007505 if(not $ParamTypeId) {
7506 next;
7507 }
7508
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007509 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007510 if(not $ParamTypeName) {
7511 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7512 }
7513 foreach my $Typedef (keys(%ChangedTypedef))
7514 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007515 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7516 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007518 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007519 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7520 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007521 if($ParamName eq "this"
7522 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007523 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007524 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007525 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007526 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007527 }
7528 else {
7529 push(@ParamArray, $ParamTypeName);
7530 }
7531 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007532 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7533 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007534 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007535 }
7536 else
7537 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007538 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007539 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007540 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007542 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7544 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007545 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007547 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7548 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007549 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007551 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7552 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007553 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007554 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007555 }
7556 }
7557 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007558 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007559 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007560 }
7561 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007562 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007563 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007564 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565}
7566
7567sub create_member_decl($$)
7568{
7569 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007570 if($TName=~/\([\*]+\)/)
7571 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007572 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7573 return $TName;
7574 }
7575 else
7576 {
7577 my @ArraySizes = ();
7578 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7579 push(@ArraySizes, $1);
7580 }
7581 return $TName." ".$Member.join("", @ArraySizes);
7582 }
7583}
7584
7585sub getFuncType($)
7586{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007587 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7588 {
7589 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7590 {
7591 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7592 {
7593 if($Type eq "method_type") {
7594 return "Method";
7595 }
7596 elsif($Type eq "function_type") {
7597 return "Function";
7598 }
7599 else {
7600 return "Other";
7601 }
7602 }
7603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007604 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007605 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007606}
7607
7608sub getFuncTypeId($)
7609{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007610 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7611 {
7612 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7613 return $1;
7614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007615 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007616 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007617}
7618
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007620{ # "._N" or "$_N" in older GCC versions
7621 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622}
7623
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007624sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007625{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007626 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7627 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007628 }
7629
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007630 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007631
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007632 if($_[1] ne "S")
7633 {
7634 $N=~s/\A[ ]+//g;
7635 $N=~s/[ ]+\Z//g;
7636 $N=~s/[ ]{2,}/ /g;
7637 }
7638
7639 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007640
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007641 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7642
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007643 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007644
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007645 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7646 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007647
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007648 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007649
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007650 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007651
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007652 if($_[1] eq "S")
7653 {
7654 if(index($N, "operator")!=-1) {
7655 $N=~s/\b(operator[ ]*)> >/$1>>/;
7656 }
7657 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007658
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007659 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007660
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007661 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662}
7663
7664sub get_HeaderDeps($$)
7665{
7666 my ($AbsPath, $LibVersion) = @_;
7667 return () if(not $AbsPath or not $LibVersion);
7668 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7669 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7670 }
7671 my %IncDir = ();
7672 detect_recursive_includes($AbsPath, $LibVersion);
7673 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7674 {
7675 next if(not $HeaderPath);
7676 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7677 my $Dir = get_dirname($HeaderPath);
7678 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7679 {
7680 my $Dep = $Dir;
7681 if($Prefix)
7682 {
7683 if($OSgroup eq "windows")
7684 { # case insensitive seach on windows
7685 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7686 next;
7687 }
7688 }
7689 elsif($OSgroup eq "macos")
7690 { # seach in frameworks
7691 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7692 {
7693 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7694 {# frameworks
7695 my ($HFramework, $HName) = ($1, $2);
7696 $Dep = $HFramework;
7697 }
7698 else
7699 {# mismatch
7700 next;
7701 }
7702 }
7703 }
7704 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7705 { # Linux, FreeBSD
7706 next;
7707 }
7708 }
7709 if(not $Dep)
7710 { # nothing to include
7711 next;
7712 }
7713 if(is_default_include_dir($Dep))
7714 { # included by the compiler
7715 next;
7716 }
7717 if(get_depth($Dep)==1)
7718 { # too short
7719 next;
7720 }
7721 if(isLibcDir($Dep))
7722 { # do NOT include /usr/include/{sys,bits}
7723 next;
7724 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007725 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007726 }
7727 }
7728 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7729 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7730}
7731
7732sub sortIncPaths($$)
7733{
7734 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007735 if(not $ArrRef or $#{$ArrRef}<0) {
7736 return $ArrRef;
7737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007738 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7739 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007740 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007741 return $ArrRef;
7742}
7743
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007744sub sortDeps($$$)
7745{
7746 if($Header_Dependency{$_[2]}{$_[0]}
7747 and not $Header_Dependency{$_[2]}{$_[1]}) {
7748 return 1;
7749 }
7750 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7751 and $Header_Dependency{$_[2]}{$_[1]}) {
7752 return -1;
7753 }
7754 return 0;
7755}
7756
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007757sub join_P($$)
7758{
7759 my $S = "/";
7760 if($OSgroup eq "windows") {
7761 $S = "\\";
7762 }
7763 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007764}
7765
7766sub get_namespace_additions($)
7767{
7768 my $NameSpaces = $_[0];
7769 my ($Additions, $AddNameSpaceId) = ("", 1);
7770 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7771 {
7772 next if($SkipNameSpaces{$Version}{$NS});
7773 next if(not $NS or $NameSpaces->{$NS}==-1);
7774 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7775 next if($NS=~/\A__/i);
7776 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007777 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007778 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7779 my @NS_Parts = split(/::/, $NS);
7780 next if($#NS_Parts==-1);
7781 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7782 foreach my $NS_Part (@NS_Parts)
7783 {
7784 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7785 $TypeDecl_Suffix .= "}";
7786 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007787 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007788 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7789 $Additions.=" $TypeDecl\n $FuncDecl\n";
7790 $AddNameSpaceId+=1;
7791 }
7792 return $Additions;
7793}
7794
7795sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007796{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007797 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007798 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007799 if($Fmt eq "windows")
7800 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007801 $Path=~s/\//\\/g;
7802 $Path=lc($Path);
7803 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007804 else
7805 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007806 $Path=~s/\\/\//g;
7807 }
7808 return $Path;
7809}
7810
7811sub inc_opt($$)
7812{
7813 my ($Path, $Style) = @_;
7814 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007815 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007816 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007817 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007818 return "-I\"".path_format($Path, "unix")."\"";
7819 }
7820 elsif($OSgroup eq "macos"
7821 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007822 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007823 return "-F".esc(get_dirname($Path));
7824 }
7825 else {
7826 return "-I".esc($Path);
7827 }
7828 }
7829 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007830 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007831 }
7832 return "";
7833}
7834
7835sub platformSpecs($)
7836{
7837 my $LibVersion = $_[0];
7838 my $Arch = getArch($LibVersion);
7839 if($OStarget eq "symbian")
7840 { # options for GCCE compiler
7841 my %Symbian_Opts = map {$_=>1} (
7842 "-D__GCCE__",
7843 "-DUNICODE",
7844 "-fexceptions",
7845 "-D__SYMBIAN32__",
7846 "-D__MARM_INTERWORK__",
7847 "-D_UNICODE",
7848 "-D__S60_50__",
7849 "-D__S60_3X__",
7850 "-D__SERIES60_3X__",
7851 "-D__EPOC32__",
7852 "-D__MARM__",
7853 "-D__EABI__",
7854 "-D__MARM_ARMV5__",
7855 "-D__SUPPORT_CPP_EXCEPTIONS__",
7856 "-march=armv5t",
7857 "-mapcs",
7858 "-mthumb-interwork",
7859 "-DEKA2",
7860 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7861 );
7862 return join(" ", keys(%Symbian_Opts));
7863 }
7864 elsif($OSgroup eq "windows"
7865 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7866 { # add options to MinGW compiler
7867 # to simulate the MSVC compiler
7868 my %MinGW_Opts = map {$_=>1} (
7869 "-D_WIN32",
7870 "-D_STDCALL_SUPPORTED",
7871 "-D__int64=\"long long\"",
7872 "-D__int32=int",
7873 "-D__int16=short",
7874 "-D__int8=char",
7875 "-D__possibly_notnullterminated=\" \"",
7876 "-D__nullterminated=\" \"",
7877 "-D__nullnullterminated=\" \"",
7878 "-D__w64=\" \"",
7879 "-D__ptr32=\" \"",
7880 "-D__ptr64=\" \"",
7881 "-D__forceinline=inline",
7882 "-D__inline=inline",
7883 "-D__uuidof(x)=IID()",
7884 "-D__try=",
7885 "-D__except(x)=",
7886 "-D__declspec(x)=__attribute__((x))",
7887 "-D__pragma(x)=",
7888 "-D_inline=inline",
7889 "-D__forceinline=__inline",
7890 "-D__stdcall=__attribute__((__stdcall__))",
7891 "-D__cdecl=__attribute__((__cdecl__))",
7892 "-D__fastcall=__attribute__((__fastcall__))",
7893 "-D__thiscall=__attribute__((__thiscall__))",
7894 "-D_stdcall=__attribute__((__stdcall__))",
7895 "-D_cdecl=__attribute__((__cdecl__))",
7896 "-D_fastcall=__attribute__((__fastcall__))",
7897 "-D_thiscall=__attribute__((__thiscall__))",
7898 "-DSHSTDAPI_(x)=x",
7899 "-D_MSC_EXTENSIONS",
7900 "-DSECURITY_WIN32",
7901 "-D_MSC_VER=1500",
7902 "-D_USE_DECLSPECS_FOR_SAL",
7903 "-D__noop=\" \"",
7904 "-DDECLSPEC_DEPRECATED=\" \"",
7905 "-D__builtin_alignof(x)=__alignof__(x)",
7906 "-DSORTPP_PASS");
7907 if($Arch eq "x86") {
7908 $MinGW_Opts{"-D_M_IX86=300"}=1;
7909 }
7910 elsif($Arch eq "x86_64") {
7911 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7912 }
7913 elsif($Arch eq "ia64") {
7914 $MinGW_Opts{"-D_M_IA64=300"}=1;
7915 }
7916 return join(" ", keys(%MinGW_Opts));
7917 }
7918 return "";
7919}
7920
7921my %C_Structure = map {$_=>1} (
7922# FIXME: Can't separate union and struct data types before dumping,
7923# so it sometimes cause compilation errors for unknown reason
7924# when trying to declare TYPE* tmp_add_class_N
7925# This is a list of such structures + list of other C structures
7926 "sigval",
7927 "sigevent",
7928 "sigaction",
7929 "sigvec",
7930 "sigstack",
7931 "timeval",
7932 "timezone",
7933 "rusage",
7934 "rlimit",
7935 "wait",
7936 "flock",
7937 "stat",
7938 "_stat",
7939 "stat32",
7940 "_stat32",
7941 "stat64",
7942 "_stat64",
7943 "_stati64",
7944 "if_nameindex",
7945 "usb_device",
7946 "sigaltstack",
7947 "sysinfo",
7948 "timeLocale",
7949 "tcp_debug",
7950 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007951 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007952 "timespec",
7953 "random_data",
7954 "drand48_data",
7955 "_IO_marker",
7956 "_IO_FILE",
7957 "lconv",
7958 "sched_param",
7959 "tm",
7960 "itimerspec",
7961 "_pthread_cleanup_buffer",
7962 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007963 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007964 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007965 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007966 "sigcontext",
7967 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007968 # Mac
7969 "_timex",
7970 "_class_t",
7971 "_category_t",
7972 "_class_ro_t",
7973 "_protocol_t",
7974 "_message_ref_t",
7975 "_super_message_ref_t",
7976 "_ivar_t",
7977 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007978);
7979
7980sub getCompileCmd($$$)
7981{
7982 my ($Path, $Opt, $Inc) = @_;
7983 my $GccCall = $GCC_PATH;
7984 if($Opt) {
7985 $GccCall .= " ".$Opt;
7986 }
7987 $GccCall .= " -x ";
7988 if($OSgroup eq "macos") {
7989 $GccCall .= "objective-";
7990 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007991
7992 if($EMERGENCY_MODE_48)
7993 { # workaround for GCC 4.8 (C only)
7994 $GccCall .= "c++";
7995 }
7996 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007997 { # compile as "C++" header
7998 # to obtain complete dump using GCC 4.0
7999 $GccCall .= "c++-header";
8000 }
8001 else
8002 { # compile as "C++" source
8003 # GCC 3.3 cannot compile headers
8004 $GccCall .= "c++";
8005 }
8006 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008007 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008008 $GccCall .= " ".$Opts;
8009 }
8010 # allow extra qualifications
8011 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008012 $GccCall .= " -fpermissive";
8013 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008014 if($NoStdInc)
8015 {
8016 $GccCall .= " -nostdinc";
8017 $GccCall .= " -nostdinc++";
8018 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008019 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008020 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04008021 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008022 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008023 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008024 if($Inc)
8025 { # include paths
8026 $GccCall .= " ".$Inc;
8027 }
8028 return $GccCall;
8029}
8030
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008031sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008032{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008033 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008034 my %HeaderElems = (
8035 # Types
8036 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008037 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008038 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8039 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008040 "time.h" => ["time_t"],
8041 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008042 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8043 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008044 "stdbool.h" => ["_Bool"],
8045 "rpc/xdr.h" => ["bool_t"],
8046 "in_systm.h" => ["n_long", "n_short"],
8047 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008048 "arpa/inet.h" => ["fw_src", "ip_src"],
8049 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008050 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008051 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008052 );
8053 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008054 foreach (keys(%HeaderElems))
8055 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008056 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008057 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008058 }
8059 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008060 my %Types = ();
8061 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8062 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008063 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008064 }
8065 if(keys(%Types))
8066 {
8067 my %AddHeaders = ();
8068 foreach my $Type (keys(%Types))
8069 {
8070 if(my $Header = $AutoPreamble{$Type})
8071 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008072 if(my $Path = identifyHeader($Header, $LibVersion))
8073 {
8074 if(skipHeader($Path, $LibVersion)) {
8075 next;
8076 }
8077 $Path = path_format($Path, $OSgroup);
8078 $AddHeaders{$Path}{"Type"} = $Type;
8079 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008080 }
8081 }
8082 }
8083 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008084 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008085 }
8086 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008087 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008088}
8089
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008090sub checkCTags($)
8091{
8092 my $Path = $_[0];
8093 if(not $Path) {
8094 return;
8095 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008096 my $CTags = undef;
8097
8098 if($OSgroup eq "bsd")
8099 { # use ectags on BSD
8100 $CTags = get_CmdPath("ectags");
8101 if(not $CTags) {
8102 printMsg("WARNING", "can't find \'ectags\' program");
8103 }
8104 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008105 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008106 $CTags = get_CmdPath("ctags");
8107 }
8108 if(not $CTags)
8109 {
8110 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008111 return;
8112 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008113
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008114 if($OSgroup ne "linux")
8115 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008116 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8117 if($Info!~/exuberant/i)
8118 {
8119 printMsg("WARNING", "incompatible version of \'ctags\' program");
8120 return;
8121 }
8122 }
8123
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008124 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008125 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008126 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008127 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008128 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008129 open(CTAGS, "<", $Out);
8130 while(my $Line = <CTAGS>)
8131 {
8132 chomp($Line);
8133 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008134 if(defined $Intrinsic_Keywords{$Name})
8135 { # noise
8136 next;
8137 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008138 if($Type eq "n")
8139 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008140 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008141 next;
8142 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008143 if(index($Scpe, "struct:")==0) {
8144 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008145 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008146 if(index($Scpe, "namespace:")==0)
8147 {
8148 if($Scpe=~s/\Anamespace://) {
8149 $Name = $Scpe."::".$Name;
8150 }
8151 }
8152 $TUnit_NameSpaces{$Version}{$Name} = 1;
8153 }
8154 elsif($Type eq "p")
8155 {
8156 if(not $Scpe or index($Scpe, "namespace:")==0) {
8157 $TUnit_Funcs{$Version}{$Name} = 1;
8158 }
8159 }
8160 elsif($Type eq "x")
8161 {
8162 if(not $Scpe or index($Scpe, "namespace:")==0) {
8163 $TUnit_Vars{$Version}{$Name} = 1;
8164 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008165 }
8166 }
8167 close(CTAGS);
8168}
8169
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008170sub preChange($$)
8171{
8172 my ($HeaderPath, $IncStr) = @_;
8173
8174 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8175 my $Content = undef;
8176
8177 if($OStarget eq "windows"
8178 and get_dumpmachine($GCC_PATH)=~/mingw/i
8179 and $MinGWMode{$Version}!=-1)
8180 { # modify headers to compile by MinGW
8181 if(not $Content)
8182 { # preprocessing
8183 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8184 }
8185 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8186 { # __asm { ... }
8187 $MinGWMode{$Version}=1;
8188 }
8189 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8190 { # comments after preprocessing
8191 $MinGWMode{$Version}=1;
8192 }
8193 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8194 { # 0xffui8
8195 $MinGWMode{$Version}=1;
8196 }
8197
8198 if($MinGWMode{$Version}) {
8199 printMsg("INFO", "Using MinGW compatibility mode");
8200 }
8201 }
8202
8203 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8204 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8205 { # rename C++ keywords in C code
8206 # disable this code by -cpp-compatible option
8207 if(not $Content)
8208 { # preprocessing
8209 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8210 }
8211 my $RegExp_C = join("|", keys(%CppKeywords_C));
8212 my $RegExp_F = join("|", keys(%CppKeywords_F));
8213 my $RegExp_O = join("|", keys(%CppKeywords_O));
8214
8215 my $Detected = undef;
8216
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008217 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 +04008218 { # MATCH:
8219 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008220 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008221 # unsigned private: 8;
8222 # DO NOT MATCH:
8223 # #pragma GCC visibility push(default)
8224 $CppMode{$Version} = 1;
8225 $Detected = "$1$2$3$4" if(not defined $Detected);
8226 }
8227 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8228 { # MATCH:
8229 # int delete(...);
8230 # int explicit(...);
8231 # DO NOT MATCH:
8232 # void operator delete(...)
8233 $CppMode{$Version} = 1;
8234 $Detected = "$1$2$3" if(not defined $Detected);
8235 }
8236 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8237 { # MATCH:
8238 # int bool;
8239 # DO NOT MATCH:
8240 # bool X;
8241 # return *this;
8242 # throw;
8243 $CppMode{$Version} = 1;
8244 $Detected = "$1$2$3" if(not defined $Detected);
8245 }
8246 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8247 { # MATCH:
8248 # int operator(...);
8249 # DO NOT MATCH:
8250 # int operator()(...);
8251 $CppMode{$Version} = 1;
8252 $Detected = "$1$2$3" if(not defined $Detected);
8253 }
8254 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8255 { # MATCH:
8256 # int foo(int operator);
8257 # int foo(int operator, int other);
8258 # DO NOT MATCH:
8259 # int operator,(...);
8260 $CppMode{$Version} = 1;
8261 $Detected = "$1$2$3" if(not defined $Detected);
8262 }
8263 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8264 { # MATCH:
8265 # int foo(gboolean *bool);
8266 # DO NOT MATCH:
8267 # void setTabEnabled(int index, bool);
8268 $CppMode{$Version} = 1;
8269 $Detected = "$1$2$3" if(not defined $Detected);
8270 }
8271 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8272 { # MATCH:
8273 # int foo(int* this);
8274 # int bar(int this);
8275 # int baz(int throw);
8276 # DO NOT MATCH:
8277 # foo(X, this);
8278 $CppMode{$Version} = 1;
8279 $Detected = "$1$2$3$4" if(not defined $Detected);
8280 }
8281 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8282 { # MATCH:
8283 # struct template {...};
8284 # extern template foo(...);
8285 $CppMode{$Version} = 1;
8286 $Detected = "$1$2" if(not defined $Detected);
8287 }
8288
8289 if($CppMode{$Version} == 1)
8290 {
8291 if($Debug)
8292 {
8293 $Detected=~s/\A\s+//g;
8294 printMsg("INFO", "Detected code: \"$Detected\"");
8295 }
8296 }
8297
8298 # remove typedef enum NAME NAME;
8299 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8300 my $N = 0;
8301 while($N<=$#FwdTypedefs-1)
8302 {
8303 my $S = $FwdTypedefs[$N];
8304 if($S eq $FwdTypedefs[$N+1])
8305 {
8306 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008307 $CppMode{$Version} = 1;
8308
8309 if($Debug) {
8310 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8311 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008312 }
8313 $N+=2;
8314 }
8315
8316 if($CppMode{$Version}==1) {
8317 printMsg("INFO", "Using C++ compatibility mode");
8318 }
8319 }
8320
8321 if($CppMode{$Version}==1
8322 or $MinGWMode{$Version}==1)
8323 {
8324 my $IPath = $TMP_DIR."/dump$Version.i";
8325 writeFile($IPath, $Content);
8326 return $IPath;
8327 }
8328
8329 return undef;
8330}
8331
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008332sub getDump()
8333{
8334 if(not $GCC_PATH) {
8335 exitStatus("Error", "internal error - GCC path is not set");
8336 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008337
8338 my @Headers = keys(%{$Registered_Headers{$Version}});
8339 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8340
8341 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8342
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008343 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008344 my $HeaderPath = $TmpHeaderPath;
8345
8346 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008347 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008348 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8349 {
8350 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008351 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008352 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008353 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008354 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8355 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008356 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008357 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008358 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008359 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8360 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008362 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008363 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008364
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008365 if($ExtraInfo)
8366 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008367 if($IncludeString) {
8368 writeFile($ExtraInfo."/include-string", $IncludeString);
8369 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008370 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8371 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008372
8373 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8374 {
8375 my $REDIR = "";
8376 foreach my $P1 (sort @Redirects) {
8377 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8378 }
8379 writeFile($ExtraInfo."/include-redirect", $REDIR);
8380 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008381 }
8382
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008383 if(not keys(%{$TargetHeaders{$Version}}))
8384 { # Target headers
8385 addTargetHeaders($Version);
8386 }
8387
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008388 # clean memory
8389 %RecursiveIncludes = ();
8390 %Header_Include_Prefix = ();
8391 %Header_Includes = ();
8392
8393 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008394 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008395 delete($Cache{"detect_header_includes"});
8396 delete($Cache{"selectSystemHeader"});
8397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008398 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008399 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8400 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008401
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008402 if($ExtraInfo)
8403 { # extra information for other tools
8404 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8405 }
8406
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008407 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008408 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008409 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008410
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008411 if($COMMON_LANGUAGE{$Version} eq "C++") {
8412 checkCTags($Pre);
8413 }
8414
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008415 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8416 { # try to correct the preprocessor output
8417 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008418 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008420 if($COMMON_LANGUAGE{$Version} eq "C++")
8421 { # add classes and namespaces to the dump
8422 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008423 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008424 or $MinGWMode{$Version}==1) {
8425 $CHdump .= " -fpreprocessed";
8426 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008427 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008428 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008429 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008430 chdir($ORIG_DIR);
8431 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8432 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 my $Content = readFile($ClassDump);
8434 foreach my $ClassInfo (split(/\n\n/, $Content))
8435 {
8436 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8437 {
8438 my $CName = $1;
8439 next if($CName=~/\A(__|_objc_|_opaque_)/);
8440 $TUnit_NameSpaces{$Version}{$CName} = -1;
8441 if($CName=~/\A[\w:]+\Z/)
8442 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008443 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008444 }
8445 if($CName=~/(\w[\w:]*)::/)
8446 { # namespaces
8447 my $NS = $1;
8448 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8449 $TUnit_NameSpaces{$Version}{$NS} = 1;
8450 }
8451 }
8452 }
8453 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8454 { # read v-tables (advanced approach)
8455 my ($CName, $VTable) = ($1, $2);
8456 $ClassVTable_Content{$Version}{$CName} = $VTable;
8457 }
8458 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008459 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8460 { # add user-defined namespaces
8461 $TUnit_NameSpaces{$Version}{$NS} = 1;
8462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008463 if($Debug)
8464 { # debug mode
8465 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008466 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008467 }
8468 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008469 }
8470
8471 # add namespaces and classes
8472 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8473 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008474 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008475 }
8476 # some GCC versions don't include class methods to the TU dump by default
8477 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008478 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008479 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8480 {
8481 next if($C_Structure{$CName});
8482 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008483 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008484 if(not $Force and $GCC_44
8485 and $OSgroup eq "linux")
8486 { # optimization for linux with GCC >= 4.4
8487 # disable this code by -force option
8488 if(index($CName, "::")!=-1)
8489 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008490 next;
8491 }
8492 }
8493 else
8494 {
8495 if($CName=~/\A(.+)::[^:]+\Z/
8496 and $TUnit_Classes{$Version}{$1})
8497 { # classes inside other classes
8498 next;
8499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008500 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008501 if(defined $TUnit_Funcs{$Version}{$CName})
8502 { # the same name for a function and type
8503 next;
8504 }
8505 if(defined $TUnit_Vars{$Version}{$CName})
8506 { # the same name for a variable and type
8507 next;
8508 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008509 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8510 }
8511 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008512 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008513 }
8514 }
8515 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8516 # create TU dump
8517 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008518 if($UserLang eq "C") {
8519 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8520 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008521 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008522 or $MinGWMode{$Version}==1) {
8523 $TUdump .= " -fpreprocessed";
8524 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008525 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008526 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8527 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008528 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008529 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008530 if($?)
8531 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008532 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008533 { # try to recompile
8534 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008535 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008536 and index($Errors, "c99_")!=-1
8537 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008538 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008539 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008540
8541 if($Debug)
8542 {
8543 # printMsg("INFO", $Errors);
8544 }
8545
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008546 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008547 resetLogging($Version);
8548 $TMP_DIR = tempdir(CLEANUP=>1);
8549 return getDump();
8550 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008551 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008552 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008553 { # add auto preamble headers and try again
8554 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008555 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008556 foreach my $Num (0 .. $#Headers)
8557 {
8558 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008559 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8560 {
8561 push_U($Include_Preamble{$Version}, $Path);
8562 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008563 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008564 }
8565 resetLogging($Version);
8566 $TMP_DIR = tempdir(CLEANUP=>1);
8567 return getDump();
8568 }
8569 elsif($Cpp0xMode{$Version}!=-1
8570 and ($Errors=~/\Q-std=c++0x\E/
8571 or $Errors=~/is not a class or namespace/))
8572 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008573 if(check_gcc($GCC_PATH, "4.6"))
8574 {
8575 $Cpp0xMode{$Version}=-1;
8576 printMsg("INFO", "Enabling c++0x mode");
8577 resetLogging($Version);
8578 $TMP_DIR = tempdir(CLEANUP=>1);
8579 $CompilerOptions{$Version} .= " -std=c++0x";
8580 return getDump();
8581 }
8582 else {
8583 printMsg("WARNING", "Probably c++0x construction detected");
8584 }
8585
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008586 }
8587 elsif($MinGWMode{$Version}==1)
8588 { # disable MinGW mode and try again
8589 $MinGWMode{$Version}=-1;
8590 resetLogging($Version);
8591 $TMP_DIR = tempdir(CLEANUP=>1);
8592 return getDump();
8593 }
8594 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008596 else {
8597 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008599 printMsg("ERROR", "some errors occurred when compiling headers");
8600 printErrorLog($Version);
8601 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008602 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 }
8604 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008605 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008606 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008607
8608 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8609 return $TUs[0];
8610 }
8611 else
8612 {
8613 my $Msg = "can't compile header(s)";
8614 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8615 $Msg .= "\nDid you install G++?";
8616 }
8617 exitStatus("Cannot_Compile", $Msg);
8618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008619}
8620
8621sub cmd_file($)
8622{
8623 my $Path = $_[0];
8624 return "" if(not $Path or not -e $Path);
8625 if(my $CmdPath = get_CmdPath("file")) {
8626 return `$CmdPath -b \"$Path\"`;
8627 }
8628 return "";
8629}
8630
8631sub getIncString($$)
8632{
8633 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008634 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008635 my $String = "";
8636 foreach (@{$ArrRef}) {
8637 $String .= " ".inc_opt($_, $Style);
8638 }
8639 return $String;
8640}
8641
8642sub getIncPaths(@)
8643{
8644 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008645 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008646 if($INC_PATH_AUTODETECT{$Version})
8647 { # auto-detecting dependencies
8648 my %Includes = ();
8649 foreach my $HPath (@HeaderPaths)
8650 {
8651 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8652 {
8653 if($Skip_Include_Paths{$Version}{$Dir}) {
8654 next;
8655 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008656 if($SystemRoot)
8657 {
8658 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8659 next;
8660 }
8661 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008662 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008663 }
8664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008666 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008667 }
8668 }
8669 else
8670 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008671 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008672 }
8673 return \@IncPaths;
8674}
8675
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008676sub push_U($@)
8677{ # push unique
8678 if(my $Array = shift @_)
8679 {
8680 if(@_)
8681 {
8682 my %Exist = map {$_=>1} @{$Array};
8683 foreach my $Elem (@_)
8684 {
8685 if(not defined $Exist{$Elem})
8686 {
8687 push(@{$Array}, $Elem);
8688 $Exist{$Elem} = 1;
8689 }
8690 }
8691 }
8692 }
8693}
8694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695sub callPreprocessor($$$)
8696{
8697 my ($Path, $Inc, $LibVersion) = @_;
8698 return "" if(not $Path or not -f $Path);
8699 my $IncludeString=$Inc;
8700 if(not $Inc) {
8701 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8702 }
8703 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008704 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008705 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008706 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008707}
8708
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008709sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710{ # native "find" is much faster than File::Find (~6x)
8711 # also the File::Find doesn't support --maxdepth N option
8712 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008713 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008714 return () if(not $Path or not -e $Path);
8715 if($OSgroup eq "windows")
8716 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008717 $Path = get_abs_path($Path);
8718 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008719 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 if($MaxDepth!=1) {
8721 $Cmd .= " /S";
8722 }
8723 if($Type eq "d") {
8724 $Cmd .= " /AD";
8725 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008726 elsif($Type eq "f") {
8727 $Cmd .= " /A-D";
8728 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008729 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008730 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008731 {
8732 if(not $UseRegex)
8733 { # FIXME: how to search file names in MS shell?
8734 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008735 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008736 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008737 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008738 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008739 }
8740 my @AbsPaths = ();
8741 foreach my $File (@Files)
8742 {
8743 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008744 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008745 }
8746 if($Type eq "f" and not -f $File)
8747 { # skip dirs
8748 next;
8749 }
8750 push(@AbsPaths, path_format($File, $OSgroup));
8751 }
8752 if($Type eq "d") {
8753 push(@AbsPaths, $Path);
8754 }
8755 return @AbsPaths;
8756 }
8757 else
8758 {
8759 my $FindCmd = get_CmdPath("find");
8760 if(not $FindCmd) {
8761 exitStatus("Not_Found", "can't find a \"find\" command");
8762 }
8763 $Path = get_abs_path($Path);
8764 if(-d $Path and -l $Path
8765 and $Path!~/\/\Z/)
8766 { # for directories that are symlinks
8767 $Path.="/";
8768 }
8769 my $Cmd = $FindCmd." \"$Path\"";
8770 if($MaxDepth) {
8771 $Cmd .= " -maxdepth $MaxDepth";
8772 }
8773 if($Type) {
8774 $Cmd .= " -type $Type";
8775 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008776 if($Name and not $UseRegex)
8777 { # wildcards
8778 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008780 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008781 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008782 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8783 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008784 my @Files = split(/\n/, $Res);
8785 if($Name and $UseRegex)
8786 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008787 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008788 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008789 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008790 }
8791}
8792
8793sub unpackDump($)
8794{
8795 my $Path = $_[0];
8796 return "" if(not $Path or not -e $Path);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008798 $Path = get_abs_path($Path);
8799 $Path = path_format($Path, $OSgroup);
8800 my ($Dir, $FileName) = separate_path($Path);
8801 my $UnpackDir = $TMP_DIR."/unpack";
8802 rmtree($UnpackDir);
8803 mkpath($UnpackDir);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +03008804
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008805 if($FileName=~s/\Q.zip\E\Z//g)
8806 { # *.zip
8807 my $UnzipCmd = get_CmdPath("unzip");
8808 if(not $UnzipCmd) {
8809 exitStatus("Not_Found", "can't find \"unzip\" command");
8810 }
8811 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008812 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008813 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008814 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008815 }
8816 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008817 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 if(not @Contents) {
8819 exitStatus("Error", "can't extract \'$Path\'");
8820 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008821 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008822 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008823 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008824 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008825 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008826 if($OSgroup eq "windows")
8827 { # -xvzf option is not implemented in tar.exe (2003)
8828 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8829 my $TarCmd = get_CmdPath("tar");
8830 if(not $TarCmd) {
8831 exitStatus("Not_Found", "can't find \"tar\" command");
8832 }
8833 my $GzipCmd = get_CmdPath("gzip");
8834 if(not $GzipCmd) {
8835 exitStatus("Not_Found", "can't find \"gzip\" command");
8836 }
8837 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008838 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008839 if($?) {
8840 exitStatus("Error", "can't extract \'$Path\'");
8841 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008842 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008843 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008844 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008845 }
8846 chdir($ORIG_DIR);
8847 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008848 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008849 if(not @Contents) {
8850 exitStatus("Error", "can't extract \'$Path\'");
8851 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008852 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 }
8854 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008855 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008856 my $TarCmd = get_CmdPath("tar");
8857 if(not $TarCmd) {
8858 exitStatus("Not_Found", "can't find \"tar\" command");
8859 }
8860 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008861 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008862 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008863 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008864 }
8865 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008866 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008867 if(not @Contents) {
8868 exitStatus("Error", "can't extract \'$Path\'");
8869 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008870 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008871 }
8872 }
8873}
8874
8875sub createArchive($$)
8876{
8877 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008878 if(not $To) {
8879 $To = ".";
8880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008881 if(not $Path or not -e $Path
8882 or not -d $To) {
8883 return "";
8884 }
8885 my ($From, $Name) = separate_path($Path);
8886 if($OSgroup eq "windows")
8887 { # *.zip
8888 my $ZipCmd = get_CmdPath("zip");
8889 if(not $ZipCmd) {
8890 exitStatus("Not_Found", "can't find \"zip\"");
8891 }
8892 my $Pkg = $To."/".$Name.".zip";
8893 unlink($Pkg);
8894 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008895 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008896 if($?)
8897 { # cannot allocate memory (or other problems with "zip")
8898 unlink($Path);
8899 exitStatus("Error", "can't pack the ABI dump: ".$!);
8900 }
8901 chdir($ORIG_DIR);
8902 unlink($Path);
8903 return $Pkg;
8904 }
8905 else
8906 { # *.tar.gz
8907 my $TarCmd = get_CmdPath("tar");
8908 if(not $TarCmd) {
8909 exitStatus("Not_Found", "can't find \"tar\"");
8910 }
8911 my $GzipCmd = get_CmdPath("gzip");
8912 if(not $GzipCmd) {
8913 exitStatus("Not_Found", "can't find \"gzip\"");
8914 }
8915 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8916 unlink($Pkg);
8917 chdir($From);
8918 system($TarCmd, "-czf", $Pkg, $Name);
8919 if($?)
8920 { # cannot allocate memory (or other problems with "tar")
8921 unlink($Path);
8922 exitStatus("Error", "can't pack the ABI dump: ".$!);
8923 }
8924 chdir($ORIG_DIR);
8925 unlink($Path);
8926 return $To."/".$Name.".tar.gz";
8927 }
8928}
8929
8930sub is_header_file($)
8931{
8932 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8933 return $_[0];
8934 }
8935 return 0;
8936}
8937
8938sub is_not_header($)
8939{
8940 if($_[0]=~/\.\w+\Z/
8941 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8942 return 1;
8943 }
8944 return 0;
8945}
8946
8947sub is_header($$$)
8948{
8949 my ($Header, $UserDefined, $LibVersion) = @_;
8950 return 0 if(-d $Header);
8951 if(-f $Header) {
8952 $Header = get_abs_path($Header);
8953 }
8954 else
8955 {
8956 if(is_abs($Header))
8957 { # incorrect absolute path
8958 return 0;
8959 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008960 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008961 $Header = $HPath;
8962 }
8963 else
8964 { # can't find header
8965 return 0;
8966 }
8967 }
8968 if($Header=~/\.\w+\Z/)
8969 { # have an extension
8970 return is_header_file($Header);
8971 }
8972 else
8973 {
8974 if($UserDefined==2)
8975 { # specified on the command line
8976 if(cmd_file($Header)!~/HTML|XML/i) {
8977 return $Header;
8978 }
8979 }
8980 elsif($UserDefined)
8981 { # specified in the XML-descriptor
8982 # header file without an extension
8983 return $Header;
8984 }
8985 else
8986 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008987 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008988 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008989 { # !~/HTML|XML|shared|dynamic/i
8990 return $Header;
8991 }
8992 }
8993 }
8994 return 0;
8995}
8996
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008997sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008998{
8999 my $LibVersion = $_[0];
9000 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9001 {
9002 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009003 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009004
9005 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9006 detect_recursive_includes($RegHeader, $LibVersion);
9007 }
9008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009009 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9010 {
9011 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009012
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009013 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009014 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9015 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009016 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009017 }
9018 }
9019 }
9020}
9021
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009022sub familiarDirs($$)
9023{
9024 my ($D1, $D2) = @_;
9025 if($D1 eq $D2) {
9026 return 1;
9027 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009028
9029 my $U1 = index($D1, "/usr/");
9030 my $U2 = index($D2, "/usr/");
9031
9032 if($U1==0 and $U2!=0) {
9033 return 0;
9034 }
9035
9036 if($U2==0 and $U1!=0) {
9037 return 0;
9038 }
9039
9040 if(index($D2, $D1."/")==0) {
9041 return 1;
9042 }
9043
9044 # /usr/include/DIR
9045 # /home/user/DIR
9046
9047 my $DL = get_depth($D1);
9048
9049 my @Dirs1 = ($D1);
9050 while($DL - get_depth($D1)<=2
9051 and get_depth($D1)>=4
9052 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9053 push(@Dirs1, $D1);
9054 }
9055
9056 my @Dirs2 = ($D2);
9057 while(get_depth($D2)>=4
9058 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9059 push(@Dirs2, $D2);
9060 }
9061
9062 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009063 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009064 foreach my $P2 (@Dirs2)
9065 {
9066
9067 if($P1 eq $P2) {
9068 return 1;
9069 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009070 }
9071 }
9072 return 0;
9073}
9074
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009075sub readHeaders($)
9076{
9077 $Version = $_[0];
9078 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9079 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009080 if($Debug)
9081 { # debug mode
9082 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009083 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009084 }
9085 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009086}
9087
9088sub prepareTypes($)
9089{
9090 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009091 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009092 { # support for old ABI dumps
9093 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009095 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009096 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9097 if($TName=~/\A(\w+)::(\w+)/) {
9098 my ($P1, $P2) = ($1, $2);
9099 if($P1 eq $P2) {
9100 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009101 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009102 else {
9103 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009107 }
9108 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009109 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009110 { # support for old ABI dumps
9111 # V < 2.5: array size == "number of elements"
9112 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009113 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009114 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009115 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009116 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009117 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009118 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009119 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009120 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009121 $Size *= $Base{"Size"};
9122 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009123 }
9124 else
9125 { # array[] is a pointer
9126 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009127 }
9128 }
9129 }
9130 }
9131 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009132 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009133 { # support for old ABI dumps
9134 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009135 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009136 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009137 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009138 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009140 my %Type = get_Type($TypeId, $LibVersion);
9141 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9142 my %Type2 = get_Type($TypeId_2, $V2);
9143 if($Type{"Size"} ne $Type2{"Size"}) {
9144 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009145 }
9146 }
9147 }
9148 }
9149}
9150
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009151sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009152{
9153 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009154
9155 if(not keys(%{$SymbolInfo{$LibVersion}}))
9156 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009157 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009158 {
9159 if($CheckHeadersOnly) {
9160 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9161 }
9162 else {
9163 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9164 }
9165 }
9166 }
9167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009168 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009169 if(not checkDump(1, "2.10")
9170 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 { # different formats
9172 $Remangle = 1;
9173 }
9174 if($CheckHeadersOnly)
9175 { # different languages
9176 if($UserLang)
9177 { # --lang=LANG for both versions
9178 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9179 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9180 {
9181 if($UserLang eq "C++")
9182 { # remangle symbols
9183 $Remangle = 1;
9184 }
9185 elsif($UserLang eq "C")
9186 { # remove mangling
9187 $Remangle = -1;
9188 }
9189 }
9190 }
9191 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009192
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009193 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009194 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009195 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009196 { # support for old ABI dumps
9197 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9198 {
9199 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9200 {
9201 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9202 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009203 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009204 if(defined $DVal and $DVal ne "")
9205 {
9206 if($TName eq "char") {
9207 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9208 }
9209 elsif($TName eq "bool") {
9210 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9211 }
9212 }
9213 }
9214 }
9215 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009216 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009217 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009218 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9219 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009220 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009221 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9222 # + support for old ABI dumps
9223 next;
9224 }
9225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009226 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009227 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009228 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009229 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009230
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009231 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009232 if(not checkDump(1, "2.12")
9233 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009234 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009235 if($ShortName eq "operator>>")
9236 {
9237 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9238 { # corrected mangling of operator>>
9239 $SRemangle = 1;
9240 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009241 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009242 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9243 {
9244 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9245 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9246 { # corrected mangling of const global data
9247 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9248 # and incorrectly mangled by old ACC versions
9249 $SRemangle = 1;
9250 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009251 }
9252 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009253 if(not $CheckHeadersOnly)
9254 { # support for old ABI dumps
9255 if(not checkDump(1, "2.17")
9256 or not checkDump(2, "2.17"))
9257 {
9258 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9259 {
9260 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9261 {
9262 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9263 {
9264 $MnglName = $ShortName;
9265 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9266 }
9267 }
9268 }
9269 }
9270 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009271 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 { # support for old ABI dumps: some symbols are not mangled in old dumps
9273 # mangle both sets of symbols (old and new)
9274 # NOTE: remangling all symbols by the same mangler
9275 if($MnglName=~/\A_ZN(V|)K/)
9276 { # mangling may be incorrect on old ABI dumps
9277 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009278 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009279 }
9280 if($MnglName=~/\A_ZN(K|)V/)
9281 { # mangling may be incorrect on old ABI dumps
9282 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009283 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009284 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009285 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9286 or (not $ClassID and $CheckHeadersOnly)
9287 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9288 { # support for old ABI dumps, GCC >= 4.0
9289 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009290 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009292 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009293 $MangledNames{$LibVersion}{$MnglName} = 1;
9294 }
9295 }
9296 }
9297 elsif($Remangle==-1)
9298 { # remove mangling
9299 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009300 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009302 if(not $MnglName) {
9303 next;
9304 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009305
9306 # NOTE: duplicated entries in the ABI Dump
9307 if(defined $CompleteSignature{$LibVersion}{$MnglName})
9308 {
9309 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9310 {
9311 if($SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} eq "p1")
9312 {
9313 next;
9314 }
9315 }
9316 }
9317
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9319 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009320 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9321
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009323 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009324 { # support for old dumps
9325 # add "Volatile" attribute
9326 if($MnglName=~/_Z(K|)V/) {
9327 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9328 }
9329 }
9330 # symbol and its symlink have same signatures
9331 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009332 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009334
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009335 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9336 {
9337 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009338
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009339 if($SymVer{$LibVersion}{$Alias}) {
9340 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9341 }
9342 }
9343
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009344 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009345 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 }
9347 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9348 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9349 }
9350 if($ExtendedCheck)
9351 { # --ext option
9352 addExtension($LibVersion);
9353 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009354
9355 # clean memory
9356 delete($SymbolInfo{$LibVersion});
9357
9358 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 { # detect allocable classes with public exported constructors
9360 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009361 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009362 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009363 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009364 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009365 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9366 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009367 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009368 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009370 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009371 $AllocableClass{$LibVersion}{$ClassName} = 1;
9372 }
9373 }
9374 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009375 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009377 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009378 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009379 if($CheckHeadersOnly)
9380 {
9381 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9382 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9383 { # all symbols except non-virtual inline
9384 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9385 }
9386 }
9387 else {
9388 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009389 }
9390 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009391 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009392 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009393 }
9394 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009395 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009397 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009399 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009400 if(defined $Base{"Type"}
9401 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009402 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009403 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 if($Name=~/<([^<>\s]+)>/)
9405 {
9406 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9407 $ReturnedClass{$LibVersion}{$Tid} = 1;
9408 }
9409 }
9410 else {
9411 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9412 }
9413 }
9414 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009415 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009417 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009418 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009419 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009420 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009422 if($Base{"Type"}=~/Struct|Class/)
9423 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009424 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009425 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9426 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009427 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 }
9430 }
9431 }
9432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009433
9434 # mapping {short name => symbols}
9435 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009436 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009437 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009438 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009439 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009440 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009441 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009442 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009443 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9444 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009445 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009446 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009447 }
9448 }
9449 }
9450 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009451
9452 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009453 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009454 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009455 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009456 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009457 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9458 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009460 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009461 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009462 $ClassNames{$LibVersion}{$TName} = 1;
9463 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009464 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9466 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 }
9468 }
9469 }
9470 }
9471 }
9472}
9473
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009474sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009475{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009476 my ($Tid, $LibVersion) = @_;
9477 if(not $Tid) {
9478 return $Tid;
9479 }
9480
9481 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9482 {
9483 if($TName_Tid{$LibVersion}{$Name}) {
9484 return $TName_Tid{$LibVersion}{$Name};
9485 }
9486 }
9487
9488 return $Tid;
9489}
9490
9491sub register_SymbolUsage($$$)
9492{
9493 my ($InfoId, $UsedType, $LibVersion) = @_;
9494
9495 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9496 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9497 {
9498 register_TypeUsage($RTid, $UsedType, $LibVersion);
9499 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9500 }
9501 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9502 {
9503 register_TypeUsage($FCid, $UsedType, $LibVersion);
9504 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9505
9506 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9507 { # register "this" pointer
9508 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9509 }
9510 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9511 { # register "this" pointer (const method)
9512 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9513 }
9514 }
9515 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9516 {
9517 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9518 {
9519 register_TypeUsage($PTid, $UsedType, $LibVersion);
9520 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9521 }
9522 }
9523 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9524 {
9525 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9526 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9527 register_TypeUsage($TTid, $UsedType, $LibVersion);
9528 }
9529 }
9530}
9531
9532sub register_TypeUsage($$$)
9533{
9534 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009535 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009536 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009537 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009538 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009539 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009540 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009541 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009542
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009543 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009544 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009545 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009546 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009547 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9549 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9550 }
9551 }
9552
9553 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9554 {
9555 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009556 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009557 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009558 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9559 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009560 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009561 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9562 {
9563 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9564 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009565 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009566 }
9567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009568 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009569 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009570 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009571 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9572 {
9573 register_TypeUsage($MTid, $UsedType, $LibVersion);
9574 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009575 }
9576 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009577 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009578 or $TInfo{"Type"} eq "MethodPtr"
9579 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009580 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009581 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009582 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009583 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009584 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009585 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009586 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9587 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009588 }
9589 }
9590 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009591 if($TInfo{"Type"} eq "FieldPtr")
9592 {
9593 if(my $RTid = $TInfo{"Return"}) {
9594 register_TypeUsage($RTid, $UsedType, $LibVersion);
9595 }
9596 if(my $CTid = $TInfo{"Class"}) {
9597 register_TypeUsage($CTid, $UsedType, $LibVersion);
9598 }
9599 }
9600 if($TInfo{"Type"} eq "MethodPtr")
9601 {
9602 if(my $CTid = $TInfo{"Class"}) {
9603 register_TypeUsage($CTid, $UsedType, $LibVersion);
9604 }
9605 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009606 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009607 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009608 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009609 $UsedType->{$TypeId} = 1;
9610 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9611 {
9612 register_TypeUsage($BTid, $UsedType, $LibVersion);
9613 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9614 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009615 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009616 else
9617 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9618 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619 }
9620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009621}
9622
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009624{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009625 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9626
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009627 if($Level eq "Dump")
9628 {
9629 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9630 { # TODO: check if this symbol is from
9631 # base classes of other target symbols
9632 return 1;
9633 }
9634 }
9635
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009636 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9637 { # stdc++ interfaces
9638 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009639 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009640
9641 my $Target = 0;
9642 if(my $Header = $SInfo->{"Header"}) {
9643 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9644 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009645 if($ExtendedCheck)
9646 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009647 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009648 $Target = 1;
9649 }
9650 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009651 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652 {
9653 if($Target)
9654 {
9655 if($Level eq "Dump")
9656 { # dumped
9657 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009658 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009659 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009660 return 1;
9661 }
9662 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009663 else {
9664 return 1;
9665 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009666 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009667 elsif($Level eq "Source")
9668 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009669 return 1;
9670 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009671 elsif($Level eq "Binary")
9672 { # checked
9673 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9674 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9675 return 1;
9676 }
9677 }
9678 }
9679 }
9680 else
9681 { # library is available
9682 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9683 { # exported symbols
9684 return 1;
9685 }
9686 if($Level eq "Dump")
9687 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009688 if($BinaryOnly)
9689 {
9690 if($SInfo->{"Data"})
9691 {
9692 if($Target) {
9693 return 1;
9694 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009695 }
9696 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009697 else
9698 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009699 if($Target) {
9700 return 1;
9701 }
9702 }
9703 }
9704 elsif($Level eq "Source")
9705 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009706 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009707 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009708 { # skip LOCAL symbols
9709 if($Target) {
9710 return 1;
9711 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009712 }
9713 }
9714 elsif($Level eq "Binary")
9715 { # checked
9716 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9717 {
9718 if($Target) {
9719 return 1;
9720 }
9721 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009722 }
9723 }
9724 return 0;
9725}
9726
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009727sub cleanDump($)
9728{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009729 my $LibVersion = $_[0];
9730 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9731 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009732 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9733 {
9734 delete($SymbolInfo{$LibVersion}{$InfoId});
9735 next;
9736 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009737 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009738 if(not $MnglName)
9739 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009740 delete($SymbolInfo{$LibVersion}{$InfoId});
9741 next;
9742 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009743 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009744 if(not $ShortName)
9745 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009746 delete($SymbolInfo{$LibVersion}{$InfoId});
9747 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009748 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009749 if($MnglName eq $ShortName)
9750 { # remove duplicate data
9751 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009752 }
9753 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9754 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9755 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009756 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9757 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9758 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009759 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009760 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009761 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009762 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009763 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9764 {
9765 delete($TypeInfo{$LibVersion}{$Tid});
9766 next;
9767 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009768 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009769 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009771 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9772 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9773 }
9774 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009775 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9776 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9777 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009778 }
9779}
9780
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009781sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009782{
9783 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009784
9785 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9786 {
9787 if(defined $TypeInfo{$LibVersion}{$Dupl})
9788 {
9789 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9790 { # duplicate
9791 return 0;
9792 }
9793 }
9794 }
9795
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009796 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9797
9798 if(isBuiltIn($THeader)) {
9799 return 0;
9800 }
9801
9802 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9803 return 0;
9804 }
9805
9806 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9807 return 0;
9808 }
9809
9810 if(selfTypedef($Tid, $LibVersion)) {
9811 return 0;
9812 }
9813
9814 if(not isTargetType($Tid, $LibVersion)) {
9815 return 0;
9816 }
9817
9818 return 0;
9819}
9820
9821sub isTargetType($$)
9822{
9823 my ($Tid, $LibVersion) = @_;
9824
9825 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9826 { # derived
9827 return 1;
9828 }
9829
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009830 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009831 { # NOTE: header is defined to source if undefined (DWARF dumps)
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009832 if(not is_target_header($THeader, $LibVersion))
9833 { # from target headers
9834 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009835 }
9836 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +03009837 else
9838 { # NOTE: if type is defined in source
9839 if($UsedDump{$LibVersion}{"Public"})
9840 {
9841 if(isPrivateABI($Tid, $LibVersion)) {
9842 return 0;
9843 }
9844 else {
9845 return 1;
9846 }
9847 }
9848 else {
9849 return 0;
9850 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009851 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009852
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009853 if($SkipInternalTypes)
9854 {
9855 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9856 {
9857 return 0;
9858 }
9859 }
9860
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009861 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009862}
9863
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009864sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009865{ # remove unused data types from the ABI dump
9866 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009867
9868 my %UsedType = ();
9869
9870 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009871 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009872 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009873 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009874 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009876 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009877 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009878 next;
9879 }
9880
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009881 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009882 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009883 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009884 {
9885 my %Tree = ();
9886 register_TypeUsage($Tid, \%Tree, $LibVersion);
9887
9888 my $Tmpl = 0;
9889 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9890 {
9891 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9892 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9893 {
9894 $Tmpl = 1;
9895 last;
9896 }
9897 }
9898 if(not $Tmpl)
9899 {
9900 foreach (keys(%Tree)) {
9901 $UsedType{$_} = 1;
9902 }
9903 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009904 }
9905 }
9906 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009907
9908 my %Delete = ();
9909
9910 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009911 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009912 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009913 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009914 next;
9915 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009916
9917 if($Kind eq "Extra")
9918 {
9919 my %Tree = ();
9920 register_TypeUsage($Tid, \%Tree, $LibVersion);
9921
9922 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9923 {
9924 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9925 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9926 {
9927 $Delete{$Tid} = 1;
9928 last;
9929 }
9930 }
9931 }
9932 else
9933 {
9934 # remove type
9935 delete($TypeInfo{$LibVersion}{$Tid});
9936 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009937 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009938
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009939 if($Kind eq "Extra")
9940 { # remove duplicates
9941 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9942 {
9943 if($UsedType{$Tid})
9944 { # All & Extended
9945 next;
9946 }
9947
9948 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9949
9950 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9951 delete($TypeInfo{$LibVersion}{$Tid});
9952 }
9953 }
9954 }
9955
9956 foreach my $Tid (keys(%Delete))
9957 {
9958 delete($TypeInfo{$LibVersion}{$Tid});
9959 }
9960}
9961
9962sub check_Completeness($$)
9963{
9964 my ($Info, $LibVersion) = @_;
9965
9966 # data types
9967 if(defined $Info->{"Memb"})
9968 {
9969 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9970 {
9971 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9972 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9973 }
9974 }
9975 }
9976 if(defined $Info->{"Base"})
9977 {
9978 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9979 check_TypeInfo($Bid, $LibVersion);
9980 }
9981 }
9982 if(defined $Info->{"BaseType"}) {
9983 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9984 }
9985 if(defined $Info->{"TParam"})
9986 {
9987 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9988 {
9989 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9990 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9991 next;
9992 }
9993 if($TName eq "_BoolType") {
9994 next;
9995 }
9996 if($TName=~/\Asizeof\(/) {
9997 next;
9998 }
9999 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10000 check_TypeInfo($Tid, $LibVersion);
10001 }
10002 else
10003 {
10004 if(defined $Debug) {
10005 printMsg("WARNING", "missed type $TName");
10006 }
10007 }
10008 }
10009 }
10010
10011 # symbols
10012 if(defined $Info->{"Param"})
10013 {
10014 foreach my $Pos (keys(%{$Info->{"Param"}}))
10015 {
10016 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10017 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10018 }
10019 }
10020 }
10021 if(defined $Info->{"Return"}) {
10022 check_TypeInfo($Info->{"Return"}, $LibVersion);
10023 }
10024 if(defined $Info->{"Class"}) {
10025 check_TypeInfo($Info->{"Class"}, $LibVersion);
10026 }
10027}
10028
10029sub check_TypeInfo($$)
10030{
10031 my ($Tid, $LibVersion) = @_;
10032
10033 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10034 return;
10035 }
10036 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10037
10038 if(defined $TypeInfo{$LibVersion}{$Tid})
10039 {
10040 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10041 printMsg("ERROR", "missed type name ($Tid)");
10042 }
10043 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10044 }
10045 else {
10046 printMsg("ERROR", "missed type id $Tid");
10047 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010048}
10049
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010050sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010051{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010052 my ($TypeId, $LibVersion) = @_;
10053 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010054 if($Type{"Type"} eq "Typedef")
10055 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010056 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010057 if($Base{"Type"}=~/Class|Struct/)
10058 {
10059 if($Type{"Name"} eq $Base{"Name"}) {
10060 return 1;
10061 }
10062 elsif($Type{"Name"}=~/::(\w+)\Z/)
10063 {
10064 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10065 { # QPointer<QWidget>::QPointer
10066 return 1;
10067 }
10068 }
10069 }
10070 }
10071 return 0;
10072}
10073
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010074sub addExtension($)
10075{
10076 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010077 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010078 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010079 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010080 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010081 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10082 $TName=~s/\A(struct|union|class|enum) //;
10083 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010084
10085 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10086 "Header" => "extended.h",
10087 "ShortName" => $Symbol,
10088 "MnglName" => $Symbol,
10089 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10090 );
10091
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010092 $ExtendedSymbols{$Symbol} = 1;
10093 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10094 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010095 }
10096 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010097 $ExtendedSymbols{"external_func_0"} = 1;
10098 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10099 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010100}
10101
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010102sub findMethod($$$)
10103{
10104 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010105 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010106 {
10107 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10108 return $VirtMethodInClass;
10109 }
10110 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10111 return $VirtMethodInBaseClasses;
10112 }
10113 }
10114 return "";
10115}
10116
10117sub findMethod_Class($$$)
10118{
10119 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010120 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010121 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10122 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10123 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10124 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10125 { # search for interface with the same parameters suffix (overridden)
10126 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10127 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010128 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10129 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010130 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10131 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010132 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10133 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10134 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10135 return $Candidate;
10136 }
10137 }
10138 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010139 else
10140 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010141 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10142 return $Candidate;
10143 }
10144 }
10145 }
10146 }
10147 return "";
10148}
10149
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010150sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010151{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010152 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010153 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010155 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10156 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010157 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010158 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010160 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10161 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010162 { # pure virtual D2-destructors are marked as "virt" in the dump
10163 # virtual D2-destructors are NOT marked as "virt" in the dump
10164 # both destructors are not presented in the v-table
10165 next;
10166 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010167 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010168 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010170 }
10171}
10172
10173sub registerOverriding($)
10174{
10175 my $LibVersion = $_[0];
10176 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010177 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010178 foreach my $ClassName (@Classes)
10179 {
10180 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10181 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010182 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10183 { # pure virtuals
10184 next;
10185 }
10186 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10187 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010188 {
10189 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10190 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10191 { # both overridden virtual methods
10192 # and implemented pure virtual methods
10193 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10194 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10195 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010197 }
10198 }
10199 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10200 delete($VirtualTable{$LibVersion}{$ClassName});
10201 }
10202 }
10203}
10204
10205sub setVirtFuncPositions($)
10206{
10207 my $LibVersion = $_[0];
10208 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10209 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010210 my ($Num, $Rel) = (1, 0);
10211
10212 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010213 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010214 if($UsedDump{$LibVersion}{"DWARF"}) {
10215 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10216 }
10217 else {
10218 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10219 }
10220 foreach my $VirtFunc (@Funcs)
10221 {
10222 if($UsedDump{$LibVersion}{"DWARF"}) {
10223 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10224 }
10225 else {
10226 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10227 }
10228
10229 # set relative positions
10230 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10231 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10232 { # relative position excluding added and removed virtual functions
10233 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10234 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10235 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010239 }
10240 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010241 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010242 {
10243 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010244 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010245 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010246 }
10247 }
10248}
10249
10250sub get_sub_classes($$$)
10251{
10252 my ($ClassId, $LibVersion, $Recursive) = @_;
10253 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10254 my @Subs = ();
10255 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10256 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010257 if($Recursive)
10258 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10260 push(@Subs, $SubSubId);
10261 }
10262 }
10263 push(@Subs, $SubId);
10264 }
10265 return @Subs;
10266}
10267
10268sub get_base_classes($$$)
10269{
10270 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010271 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010272 return () if(not defined $ClassType{"Base"});
10273 my @Bases = ();
10274 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10275 keys(%{$ClassType{"Base"}}))
10276 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010277 if($Recursive)
10278 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010279 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10280 push(@Bases, $SubBaseId);
10281 }
10282 }
10283 push(@Bases, $BaseId);
10284 }
10285 return @Bases;
10286}
10287
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010288sub getVTable_Model($$)
10289{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010290 my ($ClassId, $LibVersion) = @_;
10291 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10292 my @Elements = ();
10293 foreach my $BaseId (@Bases, $ClassId)
10294 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010295 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010296 {
10297 if(defined $VirtualTable{$LibVersion}{$BName})
10298 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010299 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10300 if($UsedDump{$LibVersion}{"DWARF"}) {
10301 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10302 }
10303 else {
10304 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10305 }
10306 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010307 push(@Elements, $VFunc);
10308 }
10309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010310 }
10311 }
10312 return @Elements;
10313}
10314
10315sub getVShift($$)
10316{
10317 my ($ClassId, $LibVersion) = @_;
10318 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10319 my $VShift = 0;
10320 foreach my $BaseId (@Bases)
10321 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010322 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010323 {
10324 if(defined $VirtualTable{$LibVersion}{$BName}) {
10325 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010327 }
10328 }
10329 return $VShift;
10330}
10331
10332sub getShift($$)
10333{
10334 my ($ClassId, $LibVersion) = @_;
10335 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10336 my $Shift = 0;
10337 foreach my $BaseId (@Bases)
10338 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010339 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010340 {
10341 if($Size!=1)
10342 { # not empty base class
10343 $Shift+=$Size;
10344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010345 }
10346 }
10347 return $Shift;
10348}
10349
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010350sub getVTable_Size($$)
10351{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010352 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010353 my $Size = 0;
10354 # three approaches
10355 if(not $Size)
10356 { # real size
10357 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10358 $Size = keys(%VTable);
10359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010360 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010361 if(not $Size)
10362 { # shared library symbol size
10363 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10364 $Size /= $WORD_SIZE{$LibVersion};
10365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010366 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010367 if(not $Size)
10368 { # model size
10369 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10370 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10371 }
10372 }
10373 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010374}
10375
10376sub isCopyingClass($$)
10377{
10378 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010379 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010380}
10381
10382sub isLeafClass($$)
10383{
10384 my ($ClassId, $LibVersion) = @_;
10385 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10386}
10387
10388sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010389{ # check structured type for public fields
10390 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010391}
10392
10393sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010394{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010395 my ($TypePtr, $Skip, $Start, $End) = @_;
10396 return 0 if(not $TypePtr);
10397 if($End==-1) {
10398 $End = keys(%{$TypePtr->{"Memb"}})-1;
10399 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010400 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401 {
10402 if($Skip and $Skip->{$MemPos})
10403 { # skip removed/added fields
10404 next;
10405 }
10406 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10407 {
10408 if(isPublic($TypePtr, $MemPos)) {
10409 return ($MemPos+1);
10410 }
10411 }
10412 }
10413 return 0;
10414}
10415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010416sub isReserved($)
10417{ # reserved fields == private
10418 my $MName = $_[0];
10419 if($MName=~/reserved|padding|f_spare/i) {
10420 return 1;
10421 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010422 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010423 return 1;
10424 }
10425 if($MName=~/(pad\d+)/i) {
10426 return 1;
10427 }
10428 return 0;
10429}
10430
10431sub isPublic($$)
10432{
10433 my ($TypePtr, $FieldPos) = @_;
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010435 return 0 if(not $TypePtr);
10436 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10437 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010438
10439 my $Access = $TypePtr->{"Memb"}{$FieldPos}{"access"};
10440 if($Access eq "private")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010441 { # by access in C++ language
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010442 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030010444
10445 # by name in C language
10446 # TODO: add other methods to detect private members
10447 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10448 if($MName=~/priv|abidata|parent_object/i)
10449 { # C-styled private data
10450 return 0;
10451 }
10452 if(lc($MName) eq "abi")
10453 { # ABI information/reserved field
10454 return 0;
10455 }
10456 if(isReserved($MName))
10457 { # reserved fields
10458 return 0;
10459 }
10460
10461 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010462}
10463
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010464sub getVTable_Real($$)
10465{
10466 my ($ClassName, $LibVersion) = @_;
10467 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10468 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010469 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010470 if(defined $Type{"VTable"}) {
10471 return %{$Type{"VTable"}};
10472 }
10473 }
10474 return ();
10475}
10476
10477sub cmpVTables($)
10478{
10479 my $ClassName = $_[0];
10480 my $Res = cmpVTables_Real($ClassName, 1);
10481 if($Res==-1) {
10482 $Res = cmpVTables_Model($ClassName);
10483 }
10484 return $Res;
10485}
10486
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010487sub cmpVTables_Model($)
10488{
10489 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010490 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010491 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010492 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493 return 1;
10494 }
10495 }
10496 return 0;
10497}
10498
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500{
10501 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10503 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010504 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010505 my %VTable_Old = getVTable_Real($ClassName, 1);
10506 my %VTable_New = getVTable_Real($ClassName, 2);
10507 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010508 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010509 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010511 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010512 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10513 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010514 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010516 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 my $Entry1 = $VTable_Old{$Offset};
10519 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010521 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010522 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010524
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010525 $Entry1 = simpleVEntry($Entry1);
10526 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010527
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030010528 if($Entry1=~/ 0x/ or $Entry2=~/ 0x/)
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010529 { # NOTE: problem with vtable-dumper
10530 next;
10531 }
10532
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010533 if($Entry1 ne $Entry2)
10534 { # register as changed
10535 if($Entry1=~/::([^:]+)\Z/)
10536 {
10537 my $M1 = $1;
10538 if($Entry2=~/::([^:]+)\Z/)
10539 {
10540 my $M2 = $1;
10541 if($M1 eq $M2)
10542 { # overridden
10543 next;
10544 }
10545 }
10546 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010547 if(differentDumps("G"))
10548 {
10549 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10550 {
10551 # GCC 4.6.1: -0x00000000000000010
10552 # GCC 4.7.0: -16
10553 next;
10554 }
10555 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010556 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010557 }
10558 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010559 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560}
10561
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010562sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010563{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010564 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10566 {
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010567 my $ClassId = $TName_Tid{1}{$ClassName};
10568 if(isPrivateABI($ClassId, 1)) {
10569 next;
10570 }
10571
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010572 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573 { # already registered
10574 next;
10575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010577 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010578 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 foreach my $Symbol (@Affected)
10580 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010581 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 "Target"=>$ClassName);
10584 }
10585 }
10586 }
10587}
10588
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010589sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010591 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010592 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010593 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010594 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010595 next if(not $ClassId);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010596
10597 if(isPrivateABI($ClassId, 1)) {
10598 next;
10599 }
10600
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010601 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010602 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010603 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010604 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010605 if($TName_Tid{1}{$ClassName}
10606 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010607 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010608 if(defined $CompleteSignature{1}{$Symbol}
10609 and $CompleteSignature{1}{$Symbol}{"Virt"})
10610 { # override some method in v.1
10611 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010612 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010613 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010614 }
10615 }
10616 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010617 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010619 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010620 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010621 if($TName_Tid{2}{$ClassName}
10622 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010623 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010624 if(defined $CompleteSignature{2}{$Symbol}
10625 and $CompleteSignature{2}{$Symbol}{"Virt"})
10626 { # override some method in v.2
10627 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010628 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010630 }
10631 }
10632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010633 if($Level eq "Binary")
10634 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010635 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10637 { # check replacements, including pure virtual methods
10638 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10639 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010640 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010641 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10642 if($AddedPos==$RemovedPos)
10643 {
10644 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10645 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10646 last; # other methods will be reported as "added" or "removed"
10647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010648 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010649 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10650 {
10651 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10652 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 next;
10654 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010655 my $ProblemType = "Virtual_Replacement";
10656 my @Affected = ($RemovedVFunc);
10657 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10658 { # pure methods
10659 if(not isUsedClass($ClassId, 1, $Level))
10660 { # not a parameter of some exported method
10661 next;
10662 }
10663 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010664
10665 # affected all methods (both virtual and non-virtual ones)
10666 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10667 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010668 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010669 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010670 foreach my $AffectedInt (@Affected)
10671 {
10672 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10673 { # affected exported methods only
10674 next;
10675 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010676 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10677 next;
10678 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010679 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10680 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010681 "Target"=>get_Signature($AddedVFunc, 2),
10682 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010684 }
10685 }
10686 }
10687 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010688 if(not checkDump(1, "2.0")
10689 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010690 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010691 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 return;
10693 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010694 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010695 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010696 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010697 next if(not $ClassId_Old);
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030010698
10699 if(isPrivateABI($ClassId_Old, 1)) {
10700 next;
10701 }
10702
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010703 if(not isCreatable($ClassId_Old, 1))
10704 { # skip classes without public constructors (including auto-generated)
10705 # example: class has only a private exported or private inline constructor
10706 next;
10707 }
10708 if($ClassName=~/>/)
10709 { # skip affected template instances
10710 next;
10711 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010712 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010713 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010714 if(not $ClassId_New) {
10715 next;
10716 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010717 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010718 if($Class_New{"Type"}!~/Class|Struct/)
10719 { # became typedef
10720 if($Level eq "Binary") {
10721 next;
10722 }
10723 if($Level eq "Source")
10724 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010725 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010726 if($Class_New{"Type"}!~/Class|Struct/) {
10727 next;
10728 }
10729 $ClassId_New = $Class_New{"Tid"};
10730 }
10731 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010732
10733 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10734 { # incomplete info in the ABI dump
10735 next;
10736 }
10737
10738
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010739 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10740 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 +040010741
10742 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10743 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10744
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010745 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010746 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10747 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010748 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10749 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010750 my $Shift_Old = getShift($ClassId_Old, 1);
10751 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010752 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010753 my ($Added, $Removed) = (0, 0);
10754 my @StableBases_Old = ();
10755 foreach my $BaseId (@Bases_Old)
10756 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010757 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010758 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 push(@StableBases_Old, $BaseId);
10760 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010761 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010762 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010763 { # removed base
10764 # excluding namespace::SomeClass to SomeClass renaming
10765 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010766 if($Level eq "Binary")
10767 { # Binary-level
10768 if($Shift_Old ne $Shift_New)
10769 { # affected fields
10770 if(havePubFields(\%Class_Old)) {
10771 $ProblemKind .= "_And_Shift";
10772 }
10773 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10774 $ProblemKind .= "_And_Size";
10775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010776 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010777 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10778 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010779 { # affected v-table
10780 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010781 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010782 }
10783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010784 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10786 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010787 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10788 {
10789 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10790 if($ProblemKind=~/VTable/) {
10791 $VTableChanged_M{$SubName}=1;
10792 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010793 }
10794 }
10795 foreach my $Interface (@Affected)
10796 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010797 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10798 next;
10799 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010800 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010801 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010802 "Target"=>$BaseName,
10803 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10804 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10805 "Shift"=>abs($Shift_New-$Shift_Old) );
10806 }
10807 $Removed+=1;
10808 }
10809 }
10810 my @StableBases_New = ();
10811 foreach my $BaseId (@Bases_New)
10812 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010813 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010814 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010815 push(@StableBases_New, $BaseId);
10816 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010817 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010818 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010819 { # added base
10820 # excluding namespace::SomeClass to SomeClass renaming
10821 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010822 if($Level eq "Binary")
10823 { # Binary-level
10824 if($Shift_Old ne $Shift_New)
10825 { # affected fields
10826 if(havePubFields(\%Class_Old)) {
10827 $ProblemKind .= "_And_Shift";
10828 }
10829 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10830 $ProblemKind .= "_And_Size";
10831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010832 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010833 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10834 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010835 { # affected v-table
10836 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010837 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010838 }
10839 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010840 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010841 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10842 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010843 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10844 {
10845 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10846 if($ProblemKind=~/VTable/) {
10847 $VTableChanged_M{$SubName}=1;
10848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010849 }
10850 }
10851 foreach my $Interface (@Affected)
10852 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010853 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10854 next;
10855 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010856 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010857 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010858 "Target"=>$BaseName,
10859 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10860 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10861 "Shift"=>abs($Shift_New-$Shift_Old) );
10862 }
10863 $Added+=1;
10864 }
10865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 if($Level eq "Binary")
10867 { # Binary-level
10868 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010869 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10870 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010871 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010872 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010873 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010874 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010875 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010876 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10877 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010878 if($NewPos!=$OldPos)
10879 { # changed position of the base class
10880 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010881 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010882 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10883 next;
10884 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010885 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10886 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010887 "Target"=>$BaseName,
10888 "Old_Value"=>$OldPos-1,
10889 "New_Value"=>$NewPos-1 );
10890 }
10891 }
10892 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10893 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10894 { # became non-virtual base
10895 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10896 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010897 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10898 next;
10899 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010900 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10901 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010902 "Target"=>$BaseName );
10903 }
10904 }
10905 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10906 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10907 { # became virtual base
10908 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10909 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010910 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10911 next;
10912 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010913 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10914 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010915 "Target"=>$BaseName );
10916 }
10917 }
10918 }
10919 }
10920 # detect size changes in base classes
10921 if($Shift_Old!=$Shift_New)
10922 { # size of allocable class
10923 foreach my $BaseId (@StableBases_Old)
10924 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010925 my %BaseType = get_Type($BaseId, 1);
10926 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010927 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 if($Size_Old ne $Size_New
10929 and $Size_Old and $Size_New)
10930 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010931 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010932 if(isCopyingClass($BaseId, 1)) {
10933 $ProblemType = "Size_Of_Copying_Class";
10934 }
10935 elsif($AllocableClass{1}{$BaseType{"Name"}})
10936 {
10937 if($Size_New>$Size_Old)
10938 { # increased size
10939 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010940 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 else
10942 { # decreased size
10943 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10944 if(not havePubFields(\%Class_Old))
10945 { # affected class has no public members
10946 next;
10947 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010949 }
10950 next if(not $ProblemType);
10951 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10952 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010953 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10954 next;
10955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010956 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10957 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010958 "Target"=>$BaseType{"Name"},
10959 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10960 "New_Size"=>$Size_New*$BYTE_SIZE );
10961 }
10962 }
10963 }
10964 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010965 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010966 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010967 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010968 { # compare virtual tables size in base classes
10969 my $VShift_Old = getVShift($ClassId_Old, 1);
10970 my $VShift_New = getVShift($ClassId_New, 2);
10971 if($VShift_Old ne $VShift_New)
10972 { # changes in the base class or changes in the list of base classes
10973 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10974 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10975 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010976 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010977 foreach my $BaseId (@AllBases_Old)
10978 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010979 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010980 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010981 { # lost base
10982 next;
10983 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010984 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10985 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010986 if($VSize_Old!=$VSize_New)
10987 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010988 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010989 { # TODO: affected non-virtual methods?
10990 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010991 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10992 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010993 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010994 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010995 { # skip interfaces that have not changed the absolute virtual position
10996 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010997 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010998 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10999 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011000 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011001 $VTableChanged_M{$BaseType{"Name"}} = 1;
11002 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011003 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11004 { # the reason of the layout change: added virtual functions
11005 next if($VirtualReplacement{$VirtFunc});
11006 my $ProblemType = "Added_Virtual_Method";
11007 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11008 $ProblemType = "Added_Pure_Virtual_Method";
11009 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011010 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011011 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011012 "Target"=>get_Signature($VirtFunc, 2) );
11013 }
11014 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11015 { # the reason of the layout change: removed virtual functions
11016 next if($VirtualReplacement{$VirtFunc});
11017 my $ProblemType = "Removed_Virtual_Method";
11018 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11019 $ProblemType = "Removed_Pure_Virtual_Method";
11020 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011021 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011023 "Target"=>get_Signature($VirtFunc, 1) );
11024 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011025 }
11026 }
11027 }
11028 }
11029 }
11030 }
11031 }
11032}
11033
11034sub isCreatable($$)
11035{
11036 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011037 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038 or isCopyingClass($ClassId, $LibVersion)) {
11039 return 1;
11040 }
11041 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11042 { # Fix for incomplete data: if this class has
11043 # a base class then it should also has a constructor
11044 return 1;
11045 }
11046 if($ReturnedClass{$LibVersion}{$ClassId})
11047 { # returned by some method of this class
11048 # or any other class
11049 return 1;
11050 }
11051 return 0;
11052}
11053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011055{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011057 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11058 { # parameter of some exported method
11059 return 1;
11060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011061 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11062 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011063 { # method from target class
11064 return 1;
11065 }
11066 return 0;
11067}
11068
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011070{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011071 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011072 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011073 # - virtual
11074 # - pure-virtual
11075 # - non-virtual
11076 if($CompleteSignature{1}{$Interface}{"Data"})
11077 { # global data is not affected
11078 return;
11079 }
11080 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011081 if(not $Class_Id) {
11082 return;
11083 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011084 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011085 if(cmpVTables_Real($CName, 1)==0)
11086 { # no changes
11087 return;
11088 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 $CheckedTypes{$Level}{$CName} = 1;
11090 if($Level eq "Binary")
11091 { # Binary-level
11092 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11093 and not isUsedClass($Class_Id, 1, $Level))
11094 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011095 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011096 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011097 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011098 }
11099 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11100 {
11101 if(defined $VirtualTable{2}{$CName}{$Func}
11102 and defined $CompleteSignature{2}{$Func})
11103 {
11104 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11105 and $CompleteSignature{2}{$Func}{"PureVirt"})
11106 { # became pure virtual
11107 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11108 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011109 "Target"=>get_Signature_M($Func, 1) );
11110 $VTableChanged_M{$CName} = 1;
11111 }
11112 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11113 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11114 { # became non-pure virtual
11115 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11116 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011117 "Target"=>get_Signature_M($Func, 1) );
11118 $VTableChanged_M{$CName} = 1;
11119 }
11120 }
11121 }
11122 if($Level eq "Binary")
11123 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 # check virtual table structure
11125 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11126 {
11127 next if($Interface eq $AddedVFunc);
11128 next if($VirtualReplacement{$AddedVFunc});
11129 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11130 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11131 { # pure virtual methods affect all others (virtual and non-virtual)
11132 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011133 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011134 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011135 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011137 elsif(not defined $VirtualTable{1}{$CName}
11138 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011139 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011140 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011141 { # became polymorphous class, added v-table pointer
11142 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011145 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011146 }
11147 else
11148 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011149 my $VSize_Old = getVTable_Size($CName, 1);
11150 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011151 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011152 if(isCopyingClass($Class_Id, 1))
11153 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11154 my $ProblemType = "Added_Virtual_Method";
11155 if(isLeafClass($Class_Id, 1)) {
11156 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11157 }
11158 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11159 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011161 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 else
11164 {
11165 my $ProblemType = "Added_Virtual_Method";
11166 if(isLeafClass($Class_Id, 1)) {
11167 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11168 }
11169 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11170 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011171 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011172 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011174 }
11175 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011176 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11177 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011178 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011179 if(defined $VirtualTable{1}{$CName}
11180 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011181 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011182 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11183 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011184
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011185 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011186 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011187 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11188 foreach my $ASymbol (@Affected)
11189 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011190 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11191 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011192 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011193 next;
11194 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011195 }
11196 $CheckedSymbols{$Level}{$ASymbol} = 1;
11197 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11198 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011199 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011200 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011203 }
11204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 else {
11206 # safe
11207 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011208 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011209 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11210 {
11211 next if($VirtualReplacement{$RemovedVFunc});
11212 if($RemovedVFunc eq $Interface
11213 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11214 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011215 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 next;
11217 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011218 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011219 { # became non-polymorphous class, removed v-table pointer
11220 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11221 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011222 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011223 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011224 }
11225 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11226 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11227 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011228 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011229 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011230 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11231 next;
11232 }
11233 my $VPos_New = -1;
11234 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011235 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011236 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11237 }
11238 else
11239 {
11240 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011241 next;
11242 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011243 }
11244 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11245 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11246 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11247 {
11248 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11249 foreach my $ASymbol (@Affected)
11250 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011251 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11252 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011253 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011254 next;
11255 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011256 }
11257 my $ProblemType = "Removed_Virtual_Method";
11258 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11259 $ProblemType = "Removed_Pure_Virtual_Method";
11260 }
11261 $CheckedSymbols{$Level}{$ASymbol} = 1;
11262 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11263 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011264 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011265 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011266 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011267 }
11268 }
11269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011270 }
11271 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011272 else
11273 { # Source-level
11274 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011275 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011276 next if($Interface eq $AddedVFunc);
11277 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011278 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011279 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11280 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011281 "Target"=>get_Signature($AddedVFunc, 2) );
11282 }
11283 }
11284 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11285 {
11286 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11287 {
11288 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11289 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011290 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011291 }
11292 }
11293 }
11294}
11295
11296sub find_MemberPair_Pos_byName($$)
11297{
11298 my ($Member_Name, $Pair_Type) = @_;
11299 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11300 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11301 {
11302 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11303 {
11304 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11305 $Name=~s/\A[_]+|[_]+\Z//g;
11306 if($Name eq $Member_Name) {
11307 return $MemberPair_Pos;
11308 }
11309 }
11310 }
11311 return "lost";
11312}
11313
11314sub find_MemberPair_Pos_byVal($$)
11315{
11316 my ($Member_Value, $Pair_Type) = @_;
11317 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11318 {
11319 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11320 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11321 return $MemberPair_Pos;
11322 }
11323 }
11324 return "lost";
11325}
11326
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011327sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011328{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011329 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011330 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011331 if( $_->{"T1"} eq $_[0]
11332 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011333 {
11334 return 1;
11335 }
11336 }
11337 return 0;
11338}
11339
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011340sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011341{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011342 my %IDs = (
11343 "T1" => $_[0],
11344 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011345 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011346 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011347}
11348
11349sub isRenamed($$$$$)
11350{
11351 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11352 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11353 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011354 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011355 if(not defined $Type2->{"Memb"}{$MemPos}) {
11356 return "";
11357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011358 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011359 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011360
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011361 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11362 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011363 if($MemberPair_Pos_Rev eq "lost")
11364 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011365 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11366 { # base type match
11367 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011369 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11370 { # exact type match
11371 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011372 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011373 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11374 { # size match
11375 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011377 if(isReserved($Pair_Name))
11378 { # reserved fields
11379 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011380 }
11381 }
11382 return "";
11383}
11384
11385sub isLastElem($$)
11386{
11387 my ($Pos, $TypeRef) = @_;
11388 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030011389 if($Name=~/last|count|max|total|num/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011390 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11391 return 1;
11392 }
11393 elsif($Name=~/END|NLIMITS\Z/)
11394 { # __RLIMIT_NLIMITS
11395 return 1;
11396 }
11397 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11398 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11399 { # NImageFormats, NColorRoles
11400 return 1;
11401 }
11402 return 0;
11403}
11404
11405sub nonComparable($$)
11406{
11407 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011408
11409 my $N1 = $T1->{"Name"};
11410 my $N2 = $T2->{"Name"};
11411
11412 $N1=~s/\A(struct|union|enum) //;
11413 $N2=~s/\A(struct|union|enum) //;
11414
11415 if($N1 ne $N2
11416 and not isAnon($N1)
11417 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011418 { # different names
11419 if($T1->{"Type"} ne "Pointer"
11420 or $T2->{"Type"} ne "Pointer")
11421 { # compare base types
11422 return 1;
11423 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011424 if($N1!~/\Avoid\s*\*/
11425 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011426 {
11427 return 1;
11428 }
11429 }
11430 elsif($T1->{"Type"} ne $T2->{"Type"})
11431 { # different types
11432 if($T1->{"Type"} eq "Class"
11433 and $T2->{"Type"} eq "Struct")
11434 { # "class" to "struct"
11435 return 0;
11436 }
11437 elsif($T2->{"Type"} eq "Class"
11438 and $T1->{"Type"} eq "Struct")
11439 { # "struct" to "class"
11440 return 0;
11441 }
11442 else
11443 { # "class" to "enum"
11444 # "union" to "class"
11445 # ...
11446 return 1;
11447 }
11448 }
11449 return 0;
11450}
11451
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011452sub isOpaque($)
11453{
11454 my $T = $_[0];
11455 if(not defined $T->{"Memb"})
11456 {
11457 return 1;
11458 }
11459 return 0;
11460}
11461
11462sub removeVPtr($)
11463{ # support for old ABI dumps
11464 my $TPtr = $_[0];
11465 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11466 if($#Pos>=1)
11467 {
11468 foreach my $Pos (0 .. $#Pos-1)
11469 {
11470 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11471 }
11472 delete($TPtr->{"Memb"}{$#Pos});
11473 }
11474}
11475
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011476sub isPrivateABI($$)
11477{
11478 my ($TypeId, $LibVersion) = @_;
11479
11480 if($CheckPrivateABI) {
11481 return 0;
11482 }
11483
11484 if(defined $TypeInfo{$LibVersion}{$TypeId}{"PrivateABI"}) {
11485 return 1;
11486 }
11487
11488 return 0;
11489}
11490
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011491sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011493 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011494 return {} if(not $Type1_Id or not $Type2_Id);
11495
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011496 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011497 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011498 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011499 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011500
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011501 my %Type1 = get_Type($Type1_Id, 1);
11502 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011503 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011504 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011505 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011506
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011507 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11508 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011509
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011510 if(defined $UsedDump{1}{"DWARF"})
11511 {
11512 if($Type1_Pure{"Name"} eq "__unknown__"
11513 or $Type2_Pure{"Name"} eq "__unknown__")
11514 { # Error ABI dump
11515 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11516 }
11517 }
11518
Andrey Ponomarenkoe3419b42016-01-28 15:06:08 +030011519 if(isPrivateABI($Type1_Id, 1)) {
11520 return {};
11521 }
11522
11523 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
11524 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11525
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011526 my %SubProblems = ();
11527
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011528 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11529 {
11530 if($Type1_Pure{"Type"}=~/Struct|Union/
11531 and $Type2_Pure{"Type"}=~/Struct|Union/)
11532 {
11533 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11534 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011535 if(not defined $UsedDump{1}{"DWARF"}
11536 and not defined $UsedDump{2}{"DWARF"})
11537 {
11538 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11539 "Target"=>$Type1_Pure{"Name"},
11540 "Type_Name"=>$Type1_Pure{"Name"} );
11541 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011542
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011543 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011544 }
11545 }
11546 }
11547
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011548 if(not $Type1_Pure{"Size"}
11549 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011550 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011551 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11552 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11553 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011554 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011555 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011556 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011557 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011558 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011559 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011560 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011561 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11562 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11563 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011564
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011565 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11566 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011567 }
11568
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011569 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11570 { # support for old ABI dumps
11571 # _vptr field added in 3.0
11572 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11573 {
11574 if(defined $Type2_Pure{"Memb"}
11575 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11576 {
11577 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11578 delete($Type2_Pure{"Memb"}{0});
11579 }
11580 else {
11581 removeVPtr(\%Type2_Pure);
11582 }
11583 }
11584 }
11585 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11586 {
11587 if(defined $Type1_Pure{"Memb"}
11588 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11589 {
11590 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11591 delete($Type1_Pure{"Memb"}{0});
11592 }
11593 else {
11594 removeVPtr(\%Type1_Pure);
11595 }
11596 }
11597 }
11598 }
11599
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011600 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11601 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011602
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011603 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011604 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11605 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011606 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011607 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11608 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011609 if($Base_1{"Name"} ne $Base_2{"Name"})
11610 {
11611 if(differentDumps("G")
11612 or differentDumps("V"))
11613 { # different GCC versions or different dumps
11614 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11615 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11616 # std::__va_list and __va_list
11617 $Base_1{"Name"}=~s/\A(\w+::)+//;
11618 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011619 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11620 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011622 }
11623 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11624 and $Base_1{"Name"} ne $Base_2{"Name"})
11625 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011626 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011627 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011628 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011629 {
11630 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11631 "Target"=>$Typedef_1{"Name"},
11632 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011633 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11634 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11635 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011636 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11637 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011638
11639 if(defined $UsedDump{1}{"DWARF"})
11640 {
11641 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11642 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11643 { # Error ABI dump
11644 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11645 }
11646 }
11647
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011648 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011649 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011650 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11651 {
11652 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11653 "Target"=>$Typedef_1{"Name"},
11654 "Type_Name"=>$Typedef_1{"Name"},
11655 "Old_Value"=>$Base_1{"Name"},
11656 "New_Value"=>$Base_2{"Name"} );
11657 }
11658 else
11659 {
11660 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11661 "Target"=>$Typedef_1{"Name"},
11662 "Type_Name"=>$Typedef_1{"Name"},
11663 "Old_Value"=>$Base_1{"Name"},
11664 "New_Value"=>$Base_2{"Name"} );
11665 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011667 }
11668 }
11669 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11670 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011671 my $TT1 = $Type1_Pure{"Type"};
11672 my $TT2 = $Type2_Pure{"Type"};
11673
11674 if($TT1 ne $TT2
11675 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011676 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011677 my $Short1 = $Type1_Pure{"Name"};
11678 my $Short2 = $Type2_Pure{"Name"};
11679
11680 $Short1=~s/\A\Q$TT1\E //ig;
11681 $Short2=~s/\A\Q$TT2\E //ig;
11682
11683 if($Short1 eq $Short2)
11684 {
11685 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11686 "Target"=>$Type1_Pure{"Name"},
11687 "Type_Name"=>$Type1_Pure{"Name"},
11688 "Old_Value"=>lc($Type1_Pure{"Type"}),
11689 "New_Value"=>lc($Type2_Pure{"Type"}) );
11690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011691 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011692 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011693 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011694
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011695 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030011696
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011697 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11698 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11699 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11700 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011701 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011702 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011703 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 {
11705 my $ProblemKind = "DataType_Size";
11706 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011707 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011708 {
11709 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11710 $ProblemKind = "Size_Of_Copying_Class";
11711 }
11712 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11713 {
11714 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11715 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11716 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011717 else
11718 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011719 # descreased size of allocable class
11720 # it has no special effects
11721 }
11722 }
11723 }
11724 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11725 "Target"=>$Type1_Pure{"Name"},
11726 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011727 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011728 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011729 }
11730 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011731 if(defined $Type1_Pure{"BaseType"}
11732 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011733 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011734 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11735 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011736 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011737 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11738 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011739 }
11740 }
11741 }
11742 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11743 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11744 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11745 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11746 { # detect removed and renamed fields
11747 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11748 next if(not $Member_Name);
11749 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);
11750 if($MemberPair_Pos eq "lost")
11751 {
11752 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11753 {
11754 if(isUnnamed($Member_Name))
11755 { # support for old-version dumps
11756 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011757 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011758 next;
11759 }
11760 }
11761 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11762 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011763 $RenamedField{$Member_Pos} = $RenamedTo;
11764 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011765 }
11766 else
11767 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011768 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011769 }
11770 }
11771 elsif($Type1_Pure{"Type"} eq "Enum")
11772 {
11773 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11774 next if($Member_Value1 eq "");
11775 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11776 if($MemberPair_Pos ne "lost")
11777 { # renamed
11778 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11779 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11780 if($MemberPair_Pos_Rev eq "lost")
11781 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011782 $RenamedField{$Member_Pos} = $RenamedTo;
11783 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 }
11785 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011786 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011787 }
11788 }
11789 else
11790 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011791 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011792 }
11793 }
11794 }
11795 else
11796 { # related
11797 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11798 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11799 }
11800 }
11801 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11802 { # detect added fields
11803 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11804 next if(not $Member_Name);
11805 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);
11806 if($MemberPair_Pos eq "lost")
11807 {
11808 if(isUnnamed($Member_Name))
11809 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011810 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011811 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011812 next;
11813 }
11814 }
11815 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11816 {
11817 if(not $RenamedField_Rev{$Member_Pos})
11818 { # added
11819 $AddedField{$Member_Pos}=1;
11820 }
11821 }
11822 }
11823 }
11824 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11825 { # detect moved fields
11826 my (%RelPos, %RelPosName, %AbsPos) = ();
11827 my $Pos = 0;
11828 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11829 { # relative positions in 1st version
11830 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11831 next if(not $Member_Name);
11832 if(not $RemovedField{$Member_Pos})
11833 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011834 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011835 $RelPosName{1}{$Pos} = $Member_Name;
11836 $AbsPos{1}{$Pos++} = $Member_Pos;
11837 }
11838 }
11839 $Pos = 0;
11840 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11841 { # relative positions in 2nd version
11842 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11843 next if(not $Member_Name);
11844 if(not $AddedField{$Member_Pos})
11845 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011846 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011847 $RelPosName{2}{$Pos} = $Member_Name;
11848 $AbsPos{2}{$Pos++} = $Member_Pos;
11849 }
11850 }
11851 foreach my $Member_Name (keys(%{$RelPos{1}}))
11852 {
11853 my $RPos1 = $RelPos{1}{$Member_Name};
11854 my $AbsPos1 = $NameToPosA{$Member_Name};
11855 my $Member_Name2 = $Member_Name;
11856 if(my $RenamedTo = $RenamedField{$AbsPos1})
11857 { # renamed
11858 $Member_Name2 = $RenamedTo;
11859 }
11860 my $RPos2 = $RelPos{2}{$Member_Name2};
11861 if($RPos2 ne "" and $RPos1 ne $RPos2)
11862 { # different relative positions
11863 my $AbsPos2 = $NameToPosB{$Member_Name2};
11864 if($AbsPos1 ne $AbsPos2)
11865 { # different absolute positions
11866 my $ProblemType = "Moved_Field";
11867 if(not isPublic(\%Type1_Pure, $AbsPos1))
11868 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011869 if($Level eq "Source") {
11870 next;
11871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 $ProblemType = "Moved_Private_Field";
11873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011874 if($Level eq "Binary"
11875 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011876 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011877 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011878 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011879 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011880 if($MemSize1 ne $MemSize2) {
11881 $ProblemType .= "_And_Size";
11882 }
11883 }
11884 if($ProblemType eq "Moved_Private_Field") {
11885 next;
11886 }
11887 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11888 "Target"=>$Member_Name,
11889 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011890 "Old_Value"=>$RPos1,
11891 "New_Value"=>$RPos2 );
11892 }
11893 }
11894 }
11895 }
11896 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011897 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011898 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11899 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011900 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011901 if(my $RenamedTo = $RenamedField{$Member_Pos})
11902 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011903 if(defined $Constants{2}{$Member_Name})
11904 {
11905 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11906 { # define OLD NEW
11907 next; # Safe
11908 }
11909 }
11910
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011911 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11912 {
11913 if(isPublic(\%Type1_Pure, $Member_Pos))
11914 {
11915 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11916 "Target"=>$Member_Name,
11917 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011918 "Old_Value"=>$Member_Name,
11919 "New_Value"=>$RenamedTo );
11920 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011921 elsif(isReserved($Member_Name))
11922 {
11923 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11924 "Target"=>$Member_Name,
11925 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011926 "Old_Value"=>$Member_Name,
11927 "New_Value"=>$RenamedTo );
11928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011929 }
11930 elsif($Type1_Pure{"Type"} eq "Enum")
11931 {
11932 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11933 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11934 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011935 "Old_Value"=>$Member_Name,
11936 "New_Value"=>$RenamedTo );
11937 }
11938 }
11939 elsif($RemovedField{$Member_Pos})
11940 { # removed
11941 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11942 {
11943 my $ProblemType = "Removed_Field";
11944 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011945 or isUnnamed($Member_Name))
11946 {
11947 if($Level eq "Source") {
11948 next;
11949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 $ProblemType = "Removed_Private_Field";
11951 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011952 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011953 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011954 {
11955 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11956 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011957 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 +040011958 { # changed offset
11959 $ProblemType .= "_And_Layout";
11960 }
11961 }
11962 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11963 { # affected size
11964 $ProblemType .= "_And_Size";
11965 }
11966 }
11967 if($ProblemType eq "Removed_Private_Field") {
11968 next;
11969 }
11970 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11971 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011972 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011973 }
11974 elsif($Type2_Pure{"Type"} eq "Union")
11975 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011976 if($Level eq "Binary"
11977 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011978 {
11979 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11980 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011981 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011982 }
11983 else
11984 {
11985 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11986 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011987 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011988 }
11989 }
11990 elsif($Type1_Pure{"Type"} eq "Enum")
11991 {
11992 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11993 "Target"=>$Member_Name,
11994 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011995 "Old_Value"=>$Member_Name );
11996 }
11997 }
11998 else
11999 { # changed
12000 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12001 if($Type1_Pure{"Type"} eq "Enum")
12002 {
12003 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12004 next if($Member_Value1 eq "");
12005 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12006 next if($Member_Value2 eq "");
12007 if($Member_Value1 ne $Member_Value2)
12008 {
12009 my $ProblemType = "Enum_Member_Value";
12010 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12011 $ProblemType = "Enum_Last_Member_Value";
12012 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012013 if($SkipConstants{1}{$Member_Name}) {
12014 $ProblemType = "Enum_Private_Member_Value";
12015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012016 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12017 "Target"=>$Member_Name,
12018 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012019 "Old_Value"=>$Member_Value1,
12020 "New_Value"=>$Member_Value2 );
12021 }
12022 }
12023 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12024 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012025 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12026 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12027
12028 if($Access1 ne "private"
12029 and $Access2 eq "private")
12030 {
12031 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12032 "Target"=>$Member_Name,
12033 "Type_Name"=>$Type1_Pure{"Name"});
12034 }
12035 elsif($Access1 ne "protected"
12036 and $Access1 ne "private"
12037 and $Access2 eq "protected")
12038 {
12039 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12040 "Target"=>$Member_Name,
12041 "Type_Name"=>$Type1_Pure{"Name"});
12042 }
12043
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012044 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12045 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012046 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012047 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12048 $SizeV1 = $BSize1;
12049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012050 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012051 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12052 $SizeV2 = $BSize2;
12053 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012054 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12055 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012056 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012057 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012058 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012059 {
12060 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12061 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12062 { # field size change (including anon-structures and unions)
12063 # - same types
12064 # - unnamed types
12065 # - bitfields
12066 my $ProblemType = "Field_Size";
12067 if(not isPublic(\%Type1_Pure, $Member_Pos)
12068 or isUnnamed($Member_Name))
12069 { # should not be accessed by applications, goes to "Low Severity"
12070 # example: "abidata" members in GStreamer types
12071 $ProblemType = "Private_".$ProblemType;
12072 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012073 if(not isMemPadded($Member_Pos, $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012075 if($Type2_Pure{"Type"} ne "Union"
12076 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012078 if(getOffset($MNum-1, \%Type1_Pure, $TypeInfo{1}, getArch(1), $WORD_SIZE{1})!=getOffset($RelatedField{$MNum-1}, \%Type2_Pure, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012079 { # changed offset
12080 $ProblemType .= "_And_Layout";
12081 }
12082 }
12083 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12084 $ProblemType .= "_And_Type_Size";
12085 }
12086 }
12087 if($ProblemType eq "Private_Field_Size")
12088 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012089 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012090 if($ProblemType eq "Field_Size")
12091 {
12092 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12093 { # Low severity
12094 $ProblemType = "Struct_Field_Size_Increased";
12095 }
12096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012097 if($ProblemType)
12098 { # register a problem
12099 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12100 "Target"=>$Member_Name,
12101 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012102 "Old_Size"=>$SizeV1,
12103 "New_Size"=>$SizeV2);
12104 }
12105 }
12106 }
12107 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12108 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12109 { # do NOT check bitfield type changes
12110 next;
12111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012112 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012113 {
12114 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12115 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12116 {
12117 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12118 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012119 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012120 }
12121 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12122 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12123 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012124 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012125 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012126 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012127 }
12128 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012129 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12130 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012131 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012132 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12133 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012134
12135 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012137 or $ProblemType eq "Field_Type_And_Size"
12138 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012139 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012140 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012141 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012142 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012143 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012144 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012145 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012146 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012147 }
12148 }
12149 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12150 {
12151 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012152 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012153 }
12154 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012155 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012156 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012157 }
12158 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12159 {
12160 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012161 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012162 }
12163 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012164 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012165 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012166 }
12167 }
12168 }
12169
12170 if($Level eq "Source")
12171 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012172 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012173 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012174 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12175 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012176
12177 if($ProblemType eq "Field_Type")
12178 {
12179 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012180 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012181 }
12182 }
12183 }
12184 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012185
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012186 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012187 {
12188 my $ProblemType_Init = $ProblemType;
12189 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012190 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012191 if(not isPublic(\%Type1_Pure, $Member_Pos)
12192 or isUnnamed($Member_Name)) {
12193 $ProblemType = "Private_".$ProblemType;
12194 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012195 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 +040012196 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012197 if($Type2_Pure{"Type"} ne "Union"
12198 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012199 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012200 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 +040012201 { # changed offset
12202 $ProblemType .= "_And_Layout";
12203 }
12204 }
12205 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12206 $ProblemType .= "_And_Type_Size";
12207 }
12208 }
12209 }
12210 else
12211 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012212 # TODO: Private_Field_Type rule?
12213
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012214 if(not isPublic(\%Type1_Pure, $Member_Pos)
12215 or isUnnamed($Member_Name)) {
12216 next;
12217 }
12218 }
12219 if($ProblemType eq "Private_Field_Type_And_Size")
12220 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012221 }
12222 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12223 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012224 "Type_Name"=>$Type1_Pure{"Name"});
12225
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012226 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012227 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012228 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012229 }
12230 }
12231 if(not isPublic(\%Type1_Pure, $Member_Pos))
12232 { # do NOT check internal type changes
12233 next;
12234 }
12235 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012236 { # checking member type changes
12237 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12238
12239 my %DupProblems = ();
12240
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012241 foreach my $Sub_SubProblemType (sort keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030012243 foreach my $Sub_SubLocation (sort {length($a)<=>length($b)} sort keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012244 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012245 if(not defined $AllAffected)
12246 {
12247 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12248 next;
12249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012251
12252 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12253 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12254
12255 if(not defined $AllAffected)
12256 {
12257 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 }
12259 }
12260 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012261
12262 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012263 }
12264 }
12265 }
12266 }
12267 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12268 { # checking added members, public and private
12269 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12270 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012271 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012272 if($AddedField{$Member_Pos})
12273 { # added
12274 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12275 {
12276 my $ProblemType = "Added_Field";
12277 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012278 or isUnnamed($Member_Name))
12279 {
12280 if($Level eq "Source") {
12281 next;
12282 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 $ProblemType = "Added_Private_Field";
12284 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012285 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012286 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012287 {
12288 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12289 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012290 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 +040012291 { # changed offset
12292 $ProblemType .= "_And_Layout";
12293 }
12294 }
12295 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12296 $ProblemType .= "_And_Size";
12297 }
12298 }
12299 if($ProblemType eq "Added_Private_Field")
12300 { # skip added private fields
12301 next;
12302 }
12303 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12304 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012305 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306 }
12307 elsif($Type2_Pure{"Type"} eq "Union")
12308 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012309 if($Level eq "Binary"
12310 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012311 {
12312 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12313 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012314 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012315 }
12316 else
12317 {
12318 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12319 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012320 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012321 }
12322 }
12323 elsif($Type2_Pure{"Type"} eq "Enum")
12324 {
12325 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12326 next if($Member_Value eq "");
12327 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12328 "Target"=>$Member_Name,
12329 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012330 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012331 }
12332 }
12333 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012334
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012335 if($Type1_Pure{"Type"} eq "FuncPtr")
12336 {
12337 foreach my $PPos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Param"}}))
12338 {
12339 if(not defined $Type2_Pure{"Param"}{$PPos}) {
12340 next;
12341 }
12342
12343 my $PT1 = $Type1_Pure{"Param"}{$PPos}{"type"};
12344 my $PT2 = $Type2_Pure{"Param"}{$PPos}{"type"};
12345
12346 my $PName = "p".$PPos;
12347
12348 my $FP_SubProblems = mergeTypes($PT1, $PT2, $Level);
12349 my %DupProblems = ();
12350
12351 foreach my $FP_SubProblemType (keys(%{$FP_SubProblems}))
12352 {
12353 foreach my $FP_SubLocation (keys(%{$FP_SubProblems->{$FP_SubProblemType}}))
12354 {
12355 if(not defined $AllAffected)
12356 {
12357 if(defined $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}}) {
12358 next;
12359 }
12360 }
12361
12362 my $NewLocation = ($FP_SubLocation)?$PName."->".$FP_SubLocation:$PName;
12363 $SubProblems{$FP_SubProblemType}{$NewLocation} = $FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation};
12364
12365 if(not defined $AllAffected)
12366 {
12367 $DupProblems{$FP_SubProblems->{$FP_SubProblemType}{$FP_SubLocation}} = 1;
12368 }
12369 }
12370 }
12371
12372 %DupProblems = ();
12373 }
12374 }
12375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012376 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012377 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012378}
12379
12380sub isUnnamed($) {
12381 return $_[0]=~/\Aunnamed\d+\Z/;
12382}
12383
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012384sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012385{
12386 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012387 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12388 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12389 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12390 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012391 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012392 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012393 }
12394 return $TypeName;
12395}
12396
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012399 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012400 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012401 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12402 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012404 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12405 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012406 return () if(not $Type{"Type"});
12407 if($Type{"Type"} ne $Type_Type)
12408 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012409 return () if(not $Type{"BaseType"});
12410 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012411 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012412 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012413 return %Type;
12414}
12415
12416my %TypeSpecAttributes = (
12417 "Const" => 1,
12418 "Volatile" => 1,
12419 "ConstVolatile" => 1,
12420 "Restrict" => 1,
12421 "Typedef" => 1
12422);
12423
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012424sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012425{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012426 my ($TypeId, $Info) = @_;
12427 if(not $TypeId or not $Info
12428 or not $Info->{$TypeId}) {
12429 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012430 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012431 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12432 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12433 }
12434 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012435 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012437 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012438 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012439 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440 return %Type;
12441}
12442
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012443sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012445 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012447 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12448 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012450 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12451 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012452 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12453 my $PLevel = 0;
12454 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12455 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012457 return $PLevel if(not $Type{"BaseType"});
12458 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12459 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12460 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461}
12462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012465 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012467 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12468 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012469 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012470 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12471 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012472 return %Type if(not $Type{"BaseType"});
12473 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012474 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012475 return %Type;
12476}
12477
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012478sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012479{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012480 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012482 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12483 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012484 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012485 my $Qual = "";
12486 if($Type{"Type"} eq "Pointer") {
12487 $Qual .= "*";
12488 }
12489 elsif($Type{"Type"} eq "Ref") {
12490 $Qual .= "&";
12491 }
12492 elsif($Type{"Type"} eq "ConstVolatile") {
12493 $Qual .= "const volatile";
12494 }
12495 elsif($Type{"Type"} eq "Const"
12496 or $Type{"Type"} eq "Volatile"
12497 or $Type{"Type"} eq "Restrict") {
12498 $Qual .= lc($Type{"Type"});
12499 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012500 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 return $BQual.$Qual;
12502}
12503
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012504sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012506 my ($TypeId, $Info) = @_;
12507 if(not $TypeId or not $Info
12508 or not $Info->{$TypeId}) {
12509 return ();
12510 }
12511 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012512 return %Type if(not $Type{"BaseType"});
12513 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012514 {
12515 if($Info->{$BTid}) {
12516 return %{$Info->{$BTid}};
12517 }
12518 else { # something is going wrong
12519 return ();
12520 }
12521 }
12522 else {
12523 return %Type;
12524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012525}
12526
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012527sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012528{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012529 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012530 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012531 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12532 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012533}
12534
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012535sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012536{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012537 my $Symbol = $_[0];
12538 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12539}
12540
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012541sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012542 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12543}
12544
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012545sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012546{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012547 my ($SInfo, $LibVersion) = @_;
12548
12549 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012550 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012551 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012552 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012553 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012554 return 1;
12555 }
12556 }
12557 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012558 if(my $ShortName = $SInfo->{"ShortName"})
12559 {
12560 if(index($ShortName,"<")!=-1
12561 and index($ShortName,">")!=-1) {
12562 return 1;
12563 }
12564 }
12565
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012566 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012567}
12568
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012569sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012571 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012572 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012573 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012574 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 { # class specialization
12576 return 1;
12577 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012578 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 { # method specialization
12580 return 1;
12581 }
12582 }
12583 return 0;
12584}
12585
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012586sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012588 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012589
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012590 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591 { # non-public global data
12592 return 0;
12593 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012594
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012595 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012596 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012597 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012598 }
12599
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012600 if($Symbol=~/\A_Z/)
12601 {
12602 if($Symbol=~/[CD][3-4]E/) {
12603 return 0;
12604 }
12605 }
12606
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012607 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608 { # support for old ABI dumps in --headers-only mode
12609 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12610 {
12611 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12612 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012613 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012614 if(not $PType or $PType eq "Unknown") {
12615 return 0;
12616 }
12617 }
12618 }
12619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012620 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012622 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12623
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 if($SkipSymbols{$LibVersion}{$Symbol})
12625 { # user defined symbols to ignore
12626 return 0;
12627 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012628
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012629 if($SymbolsListPath and not $SymbolsList{$Symbol})
12630 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012631 if(not $TargetHeadersPath or not $Header
12632 or not is_target_header($Header, 1))
12633 { # -symbols-list | -headers-list
12634 return 0;
12635 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012636 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012637
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012638 if($AppPath and not $SymbolsList_App{$Symbol})
12639 { # user defined symbols (in application)
12640 return 0;
12641 }
12642
12643 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12644
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012645 if($ClassId)
12646 {
12647 if(not isTargetType($ClassId, $LibVersion)) {
12648 return 0;
12649 }
12650 }
12651
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12653 if(not $NameSpace and $ClassId)
12654 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012655 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012656 }
12657 if($NameSpace)
12658 { # user defined namespaces to ignore
12659 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12660 return 0;
12661 }
12662 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12663 { # nested namespaces
12664 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12665 return 0;
12666 }
12667 }
12668 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012669 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012670 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012671 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012672 { # --skip-headers or <skip_headers> (not <skip_including>)
12673 if($Skip==1) {
12674 return 0;
12675 }
12676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012677 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012678 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012679 { # user defined types
12680 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12681
12682 if(not $TypesList{$CName})
12683 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012684 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12685 {
12686 $CName=~s/\A\Q$NS\E\:\://g;
12687 }
12688
12689 if(not $TypesList{$CName})
12690 {
12691 my $Found = 0;
12692
12693 while($CName=~s/\:\:.+?\Z//)
12694 {
12695 if($TypesList{$CName})
12696 {
12697 $Found = 1;
12698 last;
12699 }
12700 }
12701
12702 if(not $Found) {
12703 return 0;
12704 }
12705 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012706 }
12707 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012708
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012709 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12710 { # non-target symbols
12711 return 0;
12712 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012713 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012714 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012715 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12716 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012717 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012718 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12719 { # inline virtual methods
12720 if($Type=~/InlineVirt/) {
12721 return 1;
12722 }
12723 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12724 if(not $Allocable)
12725 { # check bases
12726 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12727 {
12728 if(not isCopyingClass($DCId, $LibVersion))
12729 { # exists a derived class without default c-tor
12730 $Allocable=1;
12731 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012733 }
12734 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012735 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012736 return 0;
12737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012738 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012739 else
12740 { # inline non-virtual methods
12741 return 0;
12742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012744 }
12745 }
12746 return 1;
12747}
12748
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012749sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012750{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012751 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012752 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12753 {
12754 if(link_symbol($Symbol, 1, "+Deps"))
12755 { # linker can find a new symbol
12756 # in the old-version library
12757 # So, it's not a new symbol
12758 next;
12759 }
12760 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012761 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012762 next;
12763 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012764 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012765 }
12766}
12767
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012768sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012769{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012770 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012771 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12772 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773 if(link_symbol($Symbol, 2, "+Deps"))
12774 { # linker can find an old symbol
12775 # in the new-version library
12776 next;
12777 }
12778 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012779 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012780 next;
12781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012782 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012783 }
12784}
12785
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012787{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 my $Level = $_[0];
12789 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012790 { # checking added symbols
12791 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012792 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012793 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012794 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012795 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012796 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 { # checking removed symbols
12798 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012799 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012800 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012801 { # skip v-tables for templates, that should not be imported by applications
12802 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012803 if(my $CName = $VTableClass{$Symbol})
12804 {
12805 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12806 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012807 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012808 next;
12809 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012810 }
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030012811
12812 if($SkipSymbols{1}{$Symbol})
12813 { # user defined symbols to ignore
12814 next;
12815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012816 }
12817 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012818 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012819 }
12820 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12821 { # symbols for pure virtual methods cannot be called by clients
12822 next;
12823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825 }
12826}
12827
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012828sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012829{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012830 my ($LibVersion, $V) = @_;
12831 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12832 return $Cache{"checkDump"}{$LibVersion}{$V};
12833 }
12834 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012835}
12836
12837sub detectAdded_H($)
12838{
12839 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12841 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 if($Level eq "Source")
12843 { # remove symbol version
12844 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12845 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012846
12847 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12848 { # skip artificial constructors
12849 next;
12850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012851 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012852 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12853 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012854 next;
12855 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012856 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012857 next;
12858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 if(not defined $CompleteSignature{1}{$Symbol}
12860 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12861 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012862 if($UsedDump{2}{"SrcBin"})
12863 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012864 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012865 { # support for old and different (!) ABI dumps
12866 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12867 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012868 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012869 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012870 {
12871 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12872 {
12873 if($Lang eq "C")
12874 { # support for old ABI dumps: missed extern "C" functions
12875 next;
12876 }
12877 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012878 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012879 else
12880 {
12881 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012882 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012883 next;
12884 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012885 }
12886 }
12887 }
12888 }
12889 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012890 }
12891 }
12892}
12893
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012894sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012895{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012896 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012897 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12898 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012899 if($Level eq "Source")
12900 { # remove symbol version
12901 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12902 $Symbol=$SN;
12903 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012904 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12905 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012906 next;
12907 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012908 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012909 next;
12910 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012911 if(not defined $CompleteSignature{2}{$Symbol}
12912 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012913 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012914 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012915 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012916 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012917 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012918 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12919 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012921 if($CheckHeadersOnly)
12922 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012923 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12924 {
12925 if($Lang eq "C")
12926 { # support for old ABI dumps: missed extern "C" functions
12927 next;
12928 }
12929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012930 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012931 else
12932 {
12933 if(not link_symbol($Symbol, 1, "-Deps"))
12934 { # skip removed inline symbols
12935 next;
12936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012937 }
12938 }
12939 }
12940 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012941 if(not checkDump(1, "2.15"))
12942 {
12943 if($Symbol=~/_IT_E\Z/)
12944 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12945 next;
12946 }
12947 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012948 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12949 {
12950 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12951 {
12952 if(defined $Constants{2}{$Short})
12953 {
12954 my $Val = $Constants{2}{$Short}{"Value"};
12955 if(defined $Func_ShortName{2}{$Val})
12956 { # old name defined to new
12957 next;
12958 }
12959 }
12960 }
12961
12962 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012963 $RemovedInt{$Level}{$Symbol} = 1;
12964 if($Level eq "Source")
12965 { # search for a source-compatible equivalent
12966 setAlternative($Symbol, $Level);
12967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012968 }
12969 }
12970}
12971
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012972sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012973{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012974 my $Level = $_[0];
12975 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012976 { # checking added symbols
12977 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012978 next if($CompleteSignature{2}{$Symbol}{"Private"});
12979 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012980 if($Level eq "Binary")
12981 {
12982 if($CompleteSignature{2}{$Symbol}{"InLine"})
12983 {
12984 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12985 { # skip inline non-virtual functions
12986 next;
12987 }
12988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012989 }
12990 else
12991 { # Source
12992 if($SourceAlternative_B{$Symbol}) {
12993 next;
12994 }
12995 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012996 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012997 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012998 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012999 { # checking removed symbols
13000 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013001 next if($CompleteSignature{1}{$Symbol}{"Private"});
13002 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013003 if($Level eq "Binary")
13004 {
13005 if($CompleteSignature{1}{$Symbol}{"InLine"})
13006 {
13007 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13008 { # skip inline non-virtual functions
13009 next;
13010 }
13011 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013012 }
13013 else
13014 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013015 if(my $Alt = $SourceAlternative{$Symbol})
13016 {
13017 if(defined $CompleteSignature{1}{$Alt}
13018 and $CompleteSignature{1}{$Symbol}{"Const"})
13019 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013020 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013021 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013022 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013023 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013024 }
13025 else
13026 { # do NOT show removed symbol
13027 next;
13028 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013029 }
13030 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013031 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013032 }
13033}
13034
13035sub addParamNames($)
13036{
13037 my $LibraryVersion = $_[0];
13038 return if(not keys(%AddIntParams));
13039 my $SecondVersion = $LibraryVersion==1?2:1;
13040 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13041 {
13042 next if(not keys(%{$AddIntParams{$Interface}}));
13043 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013044 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13046 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013047 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013048 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13049 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13050 {
13051 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13052 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13053 }
13054 }
13055 else {
13056 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13057 }
13058 }
13059 }
13060 }
13061}
13062
13063sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013064{ # detect changed typedefs to show
13065 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013066 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13067 {
13068 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013069 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13070 if(not $BName1 or isAnon($BName1)) {
13071 next;
13072 }
13073 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13074 if(not $BName2 or isAnon($BName2)) {
13075 next;
13076 }
13077 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013078 $ChangedTypedef{$Typedef} = 1;
13079 }
13080 }
13081}
13082
13083sub get_symbol_suffix($$)
13084{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 my ($Symbol, $Full) = @_;
13086 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013087 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013088 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013089 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013090 if(not $Full) {
13091 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13092 }
13093 return $Suffix;
13094}
13095
13096sub get_symbol_prefix($$)
13097{
13098 my ($Symbol, $LibVersion) = @_;
13099 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13100 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13101 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013102 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013103 }
13104 return $ShortName;
13105}
13106
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013107sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013108{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 my $Symbol = $_[0];
13110 my $PSymbol = $Symbol;
13111 if(not defined $CompleteSignature{2}{$PSymbol}
13112 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13113 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13114 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013115 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013116 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013117 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013118 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013119 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13120 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013121 {
13122 if(defined $CompleteSignature{2}{$PSymbol}
13123 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13124 {
13125 $SourceAlternative{$Symbol} = $PSymbol;
13126 $SourceAlternative_B{$PSymbol} = $Symbol;
13127 if(not defined $CompleteSignature{1}{$PSymbol}
13128 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13129 $SourceReplacement{$Symbol} = $PSymbol;
13130 }
13131 }
13132 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013133 }
13134 else
13135 {
13136 foreach my $Sp ("KV", "VK", "K", "V")
13137 {
13138 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13139 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13140 {
13141 if(defined $CompleteSignature{2}{$PSymbol}
13142 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13143 {
13144 $SourceAlternative{$Symbol} = $PSymbol;
13145 $SourceAlternative_B{$PSymbol} = $Symbol;
13146 if(not defined $CompleteSignature{1}{$PSymbol}
13147 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13148 $SourceReplacement{$Symbol} = $PSymbol;
13149 }
13150 }
13151 }
13152 $PSymbol = $Symbol;
13153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013154 }
13155 }
13156 }
13157 return "";
13158}
13159
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013160sub getSymKind($$)
13161{
13162 my ($Symbol, $LibVersion) = @_;
13163 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13164 {
13165 return "Global_Data";
13166 }
13167 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13168 {
13169 return "Method";
13170 }
13171 return "Function";
13172}
13173
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013174sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013175{
13176 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013177 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013178
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013179 mergeBases($Level);
13180
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013181 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013182 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013183 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013184 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 next;
13186 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013187 if(defined $CompleteSignature{1}{$Symbol}
13188 and $CompleteSignature{1}{$Symbol}{"Header"})
13189 { # double-check added symbol
13190 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013192 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013193 next;
13194 }
13195 if($Symbol=~/\A(_Z|\?)/)
13196 { # C++
13197 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13198 }
13199 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13200 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013201 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13202 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013203 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013205 {
13206 if($TName_Tid{1}{$AffectedClass_Name})
13207 { # class should exist in previous version
13208 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13209 { # old v-table is NOT copied by old applications
13210 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13211 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013212 "Target"=>get_Signature($Symbol, 2),
13213 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013214 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013217 }
13218 }
13219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013220 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13221 { # check all removed exported symbols
13222 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223 next;
13224 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013225 if(defined $CompleteSignature{2}{$Symbol}
13226 and $CompleteSignature{2}{$Symbol}{"Header"})
13227 { # double-check removed symbol
13228 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013229 }
13230 if($CompleteSignature{1}{$Symbol}{"Private"})
13231 { # skip private methods
13232 next;
13233 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013234 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013235 next;
13236 }
13237 $CheckedSymbols{$Level}{$Symbol} = 1;
13238 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13239 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013240 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13241 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013242 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013243 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13244 {
13245 if($TName_Tid{2}{$AffectedClass_Name})
13246 { # class should exist in newer version
13247 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13248 { # old v-table is NOT copied by old applications
13249 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13250 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013251 "Target"=>get_Signature($OverriddenMethod, 1),
13252 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013253 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013256 }
13257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013258 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013259 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013261 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013263 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013264 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013265 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013267 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013268 {
13269 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13270 "Target"=>$tr_name{$Symbol},
13271 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013272 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013274 else
13275 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013276 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013277 "Target"=>$tr_name{$Symbol},
13278 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013279 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 }
13281 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013282 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013283 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013284 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013285 {
13286 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13287 "Target"=>$tr_name{$Symbol},
13288 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013289 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013291 else
13292 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013293 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 "Target"=>$tr_name{$Symbol},
13295 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013296 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013297 }
13298 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013299 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13300 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13301 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13302 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13303 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013304 {
13305 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013306 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 $ProblemType = "Global_Data_Symbol_Changed_Type";
13308 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013309 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13310 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013311 "Old_Type"=>$RTName1,
13312 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013313 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013314 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013315 }
13316 }
13317 }
13318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013321 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013322 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013323 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013324 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013325 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013326 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13327 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013328 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013329 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013331 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013332 }
13333 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13335 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013336 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013337 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013339 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 }
13341 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013342 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013344 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013345 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013346 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013347 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013348 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013349 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013351 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013352 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013353 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013354 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013356 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013359 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013360 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013361 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013365 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013366 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013367 { # "volatile" to non-"volatile"
13368
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013369 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013370 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013371 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013373 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013374 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013375 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013376 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013377 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013378 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013379 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013381 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013382 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013386 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13387 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013388 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013389 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013390 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 }
13392 }
13393 }
13394 }
13395 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013396 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13397 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013398 $CurrentSymbol = $Symbol;
13399
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013400 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13401 if($Level eq "Source")
13402 { # remove symbol version
13403 $Symbol=$SN;
13404 }
13405 else
13406 { # Binary
13407 if(not $SV)
13408 { # symbol without version
13409 if(my $VSym = $SymVer{1}{$Symbol})
13410 { # the symbol is linked with versioned symbol
13411 if($CompleteSignature{2}{$VSym}{"MnglName"})
13412 { # show report for symbol@ver only
13413 next;
13414 }
13415 elsif(not link_symbol($VSym, 2, "-Deps"))
13416 { # changed version: sym@v1 to sym@v2
13417 # do NOT show report for symbol
13418 next;
13419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013420 }
13421 }
13422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 my $PSymbol = $Symbol;
13424 if($Level eq "Source"
13425 and my $S = $SourceReplacement{$Symbol})
13426 { # take a source-compatible replacement function
13427 $PSymbol = $S;
13428 }
13429 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 { # private symbols
13431 next;
13432 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 if(not defined $CompleteSignature{1}{$Symbol}
13434 or not defined $CompleteSignature{2}{$PSymbol})
13435 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013436 next;
13437 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13439 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13440 { # no mangled name
13441 next;
13442 }
13443 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13444 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013445 { # without a header
13446 next;
13447 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013448
13449 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13450 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13451 { # became pure
13452 next;
13453 }
13454 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13455 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13456 { # became non-pure
13457 next;
13458 }
13459
13460 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13461 { # exported, target, inline virtual and pure virtual
13462 next;
13463 }
13464 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13465 { # exported, target, inline virtual and pure virtual
13466 next;
13467 }
13468
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013469 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013470 {
13471 if($CompleteSignature{1}{$Symbol}{"Data"}
13472 and $CompleteSignature{2}{$PSymbol}{"Data"})
13473 {
13474 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13475 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13476 if(defined $Value1)
13477 {
13478 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13479 if(defined $Value2)
13480 {
13481 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13482 if($Value1 ne $Value2)
13483 {
13484 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13485 "Old_Value"=>$Value1,
13486 "New_Value"=>$Value2,
13487 "Target"=>get_Signature($Symbol, 1) );
13488 }
13489 }
13490 }
13491 }
13492 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013493
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013494 if($CompleteSignature{2}{$PSymbol}{"Private"})
13495 {
13496 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13497 "Target"=>get_Signature_M($PSymbol, 2) );
13498 }
13499 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13500 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13501 {
13502 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13503 "Target"=>get_Signature_M($PSymbol, 2) );
13504 }
13505 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13506 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13507 {
13508 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13509 "Target"=>get_Signature_M($PSymbol, 2) );
13510 }
13511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013512 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013513 mergeVirtualTables($Symbol, $Level);
13514
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 if($COMPILE_ERRORS)
13516 { # if some errors occurred at the compiling stage
13517 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013518 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013519 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013520 { # missed information about parameters in newer version
13521 next;
13522 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013523 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013524 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013525 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013526 next;
13527 }
13528 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013529 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013531 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013532 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13533 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013534 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13535 "Target"=>get_Signature($Symbol, 1)
13536 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013537 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013539 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13540 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013541 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 "Target"=>get_Signature($Symbol, 1)
13543 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013545 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13546 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013548 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013549 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013550 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13551 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13552 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013553 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013554 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013555 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13556 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013557 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013558 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013559 my $ProblemType = "Virtual_Method_Position";
13560 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13561 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013562 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 if(isUsedClass($Class_Id, 1, $Level))
13564 {
13565 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013566 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013567 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013568 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13569 next;
13570 }
13571 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013572 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13574 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013575 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013576 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013577 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013579 }
13580 }
13581 }
13582 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13584 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 { # do NOT check type changes in pure virtuals
13586 next;
13587 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013588 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013589 if($Symbol=~/\A(_Z|\?)/
13590 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013592 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013594 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 }
13596 }
13597 else
13598 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013599 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013600 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013601 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013602 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13603 last if($PType2_Name eq "...");
13604 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13605 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013606 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013607 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013609 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13610 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013611 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13612 $ParamPos_Prev = "lost";
13613 }
13614 }
13615 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013616 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013617 }
13618 if($ParamPos_Prev eq "lost")
13619 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013620 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 {
13622 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013623 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013624 $ProblemType = "Added_Unnamed_Parameter";
13625 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013626 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013627 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013628 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013629 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013630 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013631 }
13632 else
13633 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013634 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013635 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013636 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013637 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13638 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013639 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013640 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013641 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013642 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013643 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013644 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013645 "Param_Type"=>$PType2_Name,
13646 "Old_Value"=>$PName_Old,
13647 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013648 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013649 }
13650 }
13651 else
13652 {
13653 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013654 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 $ProblemType = "Added_Middle_Unnamed_Parameter";
13656 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013657 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013658 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013659 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013660 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013661 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013662 }
13663 }
13664 }
13665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013666 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013668 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013669 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013670 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013671 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013672 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013673 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013674 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013675 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13676 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013677 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 }
13679 }
13680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013681 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013683 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013684 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13685 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013686 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13687 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013689 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013690 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013691 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13692 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013693 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13694 $ParamPos_New = "lost";
13695 }
13696 }
13697 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013698 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013699 }
13700 if($ParamPos_New eq "lost")
13701 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013702 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 {
13704 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013705 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 $ProblemType = "Removed_Unnamed_Parameter";
13707 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013708 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013709 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013710 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013711 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013712 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013713 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013714 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013715 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013716 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013717 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013718 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013719 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013720 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013721 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013722 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013723 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013724 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013725 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013726 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013727 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013728 "Old_Value"=>$PName,
13729 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013730 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 }
13732 }
13733 else
13734 {
13735 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013736 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013737 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13738 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013739 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013740 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013741 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013742 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013743 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013744 }
13745 }
13746 }
13747 }
13748 }
13749 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013750 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13751 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013752 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013753
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013754 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013756 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13757 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013758 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013759
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013760 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013761 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013762 if($SubProblemType eq "Return_Type_And_Size") {
13763 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13764 }
13765 elsif($SubProblemType eq "Return_Type_Format") {
13766 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13767 }
13768 else {
13769 $ProblemTypes{"Global_Data_Type"} = 1;
13770 }
13771
13772 # quals
13773 if($SubProblemType eq "Return_Type"
13774 or $SubProblemType eq "Return_Type_And_Size"
13775 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013776 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013777 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13778 { # const to non-const
13779 if($RR==2) {
13780 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13781 }
13782 else {
13783 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13784 }
13785 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013786 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013787 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13788 { # non-const to const
13789 if($RA==2) {
13790 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13791 }
13792 else {
13793 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13794 }
13795 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013796 }
13797 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013798 }
13799 else
13800 {
13801 # quals
13802 if($SubProblemType eq "Return_Type"
13803 or $SubProblemType eq "Return_Type_And_Size"
13804 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013805 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013806 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013807 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013808 if(addedQual($Old_Value, $New_Value, "volatile"))
13809 {
13810 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13811 if($Level ne "Source"
13812 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13813 $ProblemTypes{"Return_Type"} = 1;
13814 }
13815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013816 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013817 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13818 {
13819 if($RA==2) {
13820 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13821 }
13822 else {
13823 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13824 }
13825 if($Level ne "Source"
13826 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13827 $ProblemTypes{"Return_Type"} = 1;
13828 }
13829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013830 }
13831 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013832 if($Level eq "Binary"
13833 and not $CompleteSignature{1}{$Symbol}{"Data"})
13834 {
13835 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13836 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13837 { # if one of the architectures is unknown
13838 # then set other arhitecture to unknown too
13839 ($Arch1, $Arch2) = ("unknown", "unknown");
13840 }
13841 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013842 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013843 {
13844 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13845 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13846 }
13847 else
13848 {
13849 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13850 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13851 }
13852
13853 if($SubProblemType eq "Return_Type_Became_Void")
13854 {
13855 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13856 { # parameters stack has been affected
13857 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 }
13860 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013861 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013862 }
13863 }
13864 }
13865 elsif($SubProblemType eq "Return_Type_From_Void")
13866 {
13867 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13868 { # parameters stack has been affected
13869 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013870 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013871 }
13872 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013873 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013874 }
13875 }
13876 }
13877 elsif($SubProblemType eq "Return_Type"
13878 or $SubProblemType eq "Return_Type_And_Size"
13879 or $SubProblemType eq "Return_Type_Format")
13880 {
13881 if($Conv1{"Method"} ne $Conv2{"Method"})
13882 {
13883 if($Conv1{"Method"} eq "stack")
13884 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013885 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013886 }
13887 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013888 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013889 }
13890 }
13891 else
13892 {
13893 if($Conv1{"Method"} eq "reg")
13894 {
13895 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13896 {
13897 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013899 }
13900 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013901 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013902 }
13903 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013904 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013905 }
13906 }
13907 }
13908 }
13909 }
13910 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013911
13912 if(not keys(%ProblemTypes))
13913 { # default
13914 $ProblemTypes{$SubProblemType} = 1;
13915 }
13916
13917 foreach my $ProblemType (keys(%ProblemTypes))
13918 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013919 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013921 }
13922 if($ReturnType1_Id and $ReturnType2_Id)
13923 {
13924 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013925 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13926
13927 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013928
13929 if($CompleteSignature{1}{$Symbol}{"Data"})
13930 {
13931 if($Level eq "Binary")
13932 {
13933 if(get_PLevel($ReturnType1_Id, 1)==0)
13934 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013935 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013936 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013937
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013938 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13939 {
13940 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013941 {
13942 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13943 {
13944 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13945 last;
13946 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013947 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013948 }
13949 }
13950 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013951 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013952 {
13953 if(defined $GlobalDataObject{1}{$Symbol}
13954 and defined $GlobalDataObject{2}{$Symbol})
13955 {
13956 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13957 my $New_Size = $GlobalDataObject{2}{$Symbol};
13958 if($Old_Size!=$New_Size)
13959 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013960 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013961 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013962 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013963 }
13964 }
13965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013966 }
13967 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013968
13969 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013970 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013971 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013972 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013973 my $NewLocation = "retval";
13974 if($SubLocation and $SubLocation ne "retval") {
13975 $NewLocation = "retval->".$SubLocation;
13976 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013977 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13978 }
13979 }
13980
13981 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13982 {
13983 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13984 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013985 my $NewLocation = "retval";
13986 if($SubLocation and $SubLocation ne "retval") {
13987 $NewLocation = "retval->".$SubLocation;
13988 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013989 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013990 }
13991 }
13992 }
13993
13994 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013995 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13996 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13997 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013998 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013999 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014000 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14001 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014002 if($ThisPtr1_Id and $ThisPtr2_Id)
14003 {
14004 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014005 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14006 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014007 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014008 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014009 {
14010 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014011 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014012 }
14013 }
14014 }
14015 }
14016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014017 if($Level eq "Binary") {
14018 mergeVTables($Level);
14019 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014020 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14021 $CheckedSymbols{$Level}{$Symbol} = 1;
14022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014023}
14024
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014025sub rmQuals($$)
14026{
14027 my ($Value, $Qual) = @_;
14028 if(not $Qual) {
14029 return $Value;
14030 }
14031 if($Qual eq "all")
14032 { # all quals
14033 $Qual = "const|volatile|restrict";
14034 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014035 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014036 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014037 }
14038 return $Value;
14039}
14040
14041sub cmpBTypes($$$$)
14042{
14043 my ($T1, $T2, $V1, $V2) = @_;
14044 $T1 = uncover_typedefs($T1, $V1);
14045 $T2 = uncover_typedefs($T2, $V2);
14046 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14047}
14048
14049sub addedQual($$$)
14050{
14051 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014052 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014053}
14054
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014055sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014057 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014058 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014059}
14060
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014061sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014062{
14063 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14064 $Old_Value = uncover_typedefs($Old_Value, $V1);
14065 $New_Value = uncover_typedefs($New_Value, $V2);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014066
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014067 if($Old_Value eq $New_Value)
14068 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014069 return 0;
14070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014071 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014072 { # without a qual
14073 return 0;
14074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014075 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014076 { # became non-qual
14077 return 1;
14078 }
14079 else
14080 {
14081 my @BQ1 = getQualModel($Old_Value, $Qual);
14082 my @BQ2 = getQualModel($New_Value, $Qual);
14083 foreach (0 .. $#BQ1)
14084 { # removed qual
14085 if($BQ1[$_]==1
14086 and $BQ2[$_]!=1)
14087 {
14088 return 2;
14089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014090 }
14091 }
14092 return 0;
14093}
14094
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014095sub getQualModel($$)
14096{
14097 my ($Value, $Qual) = @_;
14098 if(not $Qual) {
14099 return $Value;
14100 }
14101
14102 # cleaning
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014103 while($Value=~/(\w+)/)
14104 {
14105 my $W = $1;
14106
14107 if($W eq $Qual) {
14108 $Value=~s/\b$W\b/\@/g;
14109 }
14110 else {
14111 $Value=~s/\b$W\b//g;
14112 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014113 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030014114
14115 $Value=~s/\@/$Qual/g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014116 $Value=~s/[^\*\&\w]+//g;
14117
14118 # modeling
14119 # int*const*const == 011
14120 # int**const == 001
14121 my @Model = ();
14122 my @Elems = split(/[\*\&]/, $Value);
14123 if(not @Elems) {
14124 return (0);
14125 }
14126 foreach (@Elems)
14127 {
14128 if($_ eq $Qual) {
14129 push(@Model, 1);
14130 }
14131 else {
14132 push(@Model, 0);
14133 }
14134 }
14135
14136 return @Model;
14137}
14138
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014139my %StringTypes = map {$_=>1} (
14140 "char*",
14141 "char const*"
14142);
14143
14144my %CharTypes = map {$_=>1} (
14145 "char",
14146 "char const"
14147);
14148
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149sub showVal($$$)
14150{
14151 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014152 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014153 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014154 if(substr($Value, 0, 2) eq "_Z")
14155 {
14156 if(my $Unmangled = $tr_name{$Value}) {
14157 return $Unmangled;
14158 }
14159 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014160 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014161 { # strings
14162 return "\"$Value\"";
14163 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014164 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014165 { # characters
14166 return "\'$Value\'";
14167 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014168 if($Value eq "")
14169 { # other
14170 return "\'\'";
14171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014172 return $Value;
14173}
14174
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014175sub getRegs($$$)
14176{
14177 my ($LibVersion, $Symbol, $Pos) = @_;
14178
14179 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14180 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014181 my %Regs = ();
14182 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14183 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014184 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014185 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14186 }
14187 }
14188
14189 return join(", ", sort keys(%Regs));
14190 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014191 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14192 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14193 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14194 {
14195 return "unknown";
14196 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014197
14198 return undef;
14199}
14200
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014201sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014202{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014203 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014204 if(not $Symbol) {
14205 return;
14206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014207 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14208 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14209 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14210 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014211 if(not $PType1_Id
14212 or not $PType2_Id) {
14213 return;
14214 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014215
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014216 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014217 { # do not merge "this"
14218 if($PName1 eq "this" or $PName2 eq "this") {
14219 return;
14220 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014221 }
14222
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014223 my %Type1 = get_Type($PType1_Id, 1);
14224 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014225
14226 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14227
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014228 my %BaseType1 = get_BaseType($PType1_Id, 1);
14229 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014230
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014231 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014232
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014233 if($Level eq "Binary")
14234 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014235 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014236 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14237 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14238 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14239 {
14240 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014241 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014242 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014243 }
14244 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14245 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14246 {
14247 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014248 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014249 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014251 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014252
14253 if(defined $UsedDump{1}{"DWARF"}
14254 and defined $UsedDump{2}{"DWARF"})
14255 {
14256 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14257 {
14258 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14259 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014260
14261 if($Old_Regs ne "unknown"
14262 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014263 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014264 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014265 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014266 if($Old_Regs ne $New_Regs)
14267 {
14268 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14269 "Target"=>$PName1,
14270 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14271 "Old_Value"=>$Old_Regs,
14272 "New_Value"=>$New_Regs );
14273 }
14274 }
14275 elsif($Old_Regs and not $New_Regs)
14276 {
14277 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014278 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014279 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014280 "Old_Value"=>$Old_Regs );
14281 }
14282 elsif(not $Old_Regs and $New_Regs)
14283 {
14284 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14285 "Target"=>$PName1,
14286 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014287 "New_Value"=>$New_Regs );
14288 }
14289 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014290
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014291 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14292 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14293 {
14294 if($Old_Offset ne $New_Offset)
14295 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014296 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14297 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14298
14299 $Old_Offset = $Old_Offset - $Start1;
14300 $New_Offset = $New_Offset - $Start2;
14301
14302 if($Old_Offset ne $New_Offset)
14303 {
14304 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14305 "Target"=>$PName1,
14306 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14307 "Old_Value"=>$Old_Offset,
14308 "New_Value"=>$New_Offset );
14309 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014310 }
14311 }
14312 }
14313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014315 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14316 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014317 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014318 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014319 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14320 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014321 if(not checkDump(1, "2.13")
14322 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014323 { # support for old ABI dumps
14324 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014325 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014326 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014327 and $Value_Old eq "false" and $Value_New eq "0")
14328 { # int class::method ( bool p = 0 );
14329 # old ABI dumps: "false"
14330 # new ABI dumps: "0"
14331 $Value_Old = "0";
14332 }
14333 }
14334 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014335 if(not checkDump(1, "2.18")
14336 and checkDump(2, "2.18"))
14337 { # support for old ABI dumps
14338 if(not defined $Value_Old
14339 and substr($Value_New, 0, 2) eq "_Z") {
14340 $Value_Old = $Value_New;
14341 }
14342 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014343 if(defined $Value_Old)
14344 {
14345 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14346 if(defined $Value_New)
14347 {
14348 $Value_New = showVal($Value_New, $PType2_Id, 2);
14349 if($Value_Old ne $Value_New)
14350 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014351 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014352 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014353 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014354 "Old_Value"=>$Value_Old,
14355 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014356 }
14357 }
14358 else
14359 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014360 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014361 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014362 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014363 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014364 }
14365 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014366 elsif(defined $Value_New)
14367 {
14368 $Value_New = showVal($Value_New, $PType2_Id, 2);
14369 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14370 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014371 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014372 "New_Value"=>$Value_New );
14373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014374 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014375
14376 if($ChkRnmd)
14377 {
14378 if($PName1 and $PName2 and $PName1 ne $PName2
14379 and $PType1_Id!=-1 and $PType2_Id!=-1
14380 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14381 { # except unnamed "..." value list (Id=-1)
14382 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14383 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014384 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014385 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14386 "Old_Value"=>$PName1,
14387 "New_Value"=>$PName2,
14388 "New_Signature"=>get_Signature($Symbol, 2) );
14389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014393 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014395 foreach my $SubProblemType (keys(%SubProblems))
14396 { # add new problems, remove false alarms
14397 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14398 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014399
14400 # quals
14401 if($SubProblemType eq "Parameter_Type"
14402 or $SubProblemType eq "Parameter_Type_And_Size"
14403 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014405 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014407 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014408 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014409 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014410 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14411 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14412 }
14413 }
14414 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14415 {
14416 if(removedQual($Old_Value, $New_Value, "volatile")) {
14417 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014418 }
14419 }
14420 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14421 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14422 { # int to "int const"
14423 delete($SubProblems{$SubProblemType});
14424 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014425 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014426 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14427 { # "int const" to int
14428 delete($SubProblems{$SubProblemType});
14429 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014430 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14431 { # "const" to non-"const"
14432 if($RR==2) {
14433 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14434 }
14435 else {
14436 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14437 }
14438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014439 }
14440 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014441
14442 if($Level eq "Source")
14443 {
14444 foreach my $SubProblemType (keys(%SubProblems))
14445 {
14446 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14447 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14448
14449 if($SubProblemType eq "Parameter_Type")
14450 {
14451 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14452 delete($SubProblems{$SubProblemType});
14453 }
14454 }
14455 }
14456 }
14457
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014458 foreach my $SubProblemType (keys(%SubProblems))
14459 { # modify/register problems
14460 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14461 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014462 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14463 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465 my $NewProblemType = $SubProblemType;
14466 if($Old_Value eq "..." and $New_Value ne "...")
14467 { # change from "..." to "int"
14468 if($ParamPos1==0)
14469 { # ISO C requires a named argument before "..."
14470 next;
14471 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014472 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014473 }
14474 elsif($New_Value eq "..." and $Old_Value ne "...")
14475 { # change from "int" to "..."
14476 if($ParamPos2==0)
14477 { # ISO C requires a named argument before "..."
14478 next;
14479 }
14480 $NewProblemType = "Parameter_Became_VaList";
14481 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014482 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014483 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014484 {
14485 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014486 if($Arch1 eq "unknown"
14487 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014488 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014489 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014490 ($Arch1, $Arch2) = ("unknown", "unknown");
14491 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014492 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014493 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014494 { # real
14495 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14496 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14497 }
14498 else
14499 { # model
14500 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14501 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14502 }
14503 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014504 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014505 if($Conv1{"Method"} eq "stack")
14506 {
14507 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14508 $NewProblemType = "Parameter_Type_And_Stack";
14509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014511 elsif($Conv1{"Method"} eq "reg")
14512 {
14513 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14514 $NewProblemType = "Parameter_Type_And_Register";
14515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014516 }
14517 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014518 elsif($Conv1{"Method"} ne "unknown"
14519 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014521 if($Conv1{"Method"} eq "stack") {
14522 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014523 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014524 elsif($Conv1{"Method"} eq "register") {
14525 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014526 }
14527 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014528 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14529 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014530 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014531 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014532 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014533 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014534 "New_Signature"=>get_Signature($Symbol, 2) );
14535 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014536 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014537
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014539
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014541 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14542 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014543 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014544 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014545 {
14546 my $NewProblemType = $SubProblemType;
14547 if($SubProblemType eq "DataType_Size")
14548 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014549 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014550 { # stack has been affected
14551 $NewProblemType = "DataType_Size_And_Stack";
14552 }
14553 }
14554 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014555 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014556 }
14557 }
14558}
14559
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014560sub find_ParamPair_Pos_byName($$$)
14561{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014562 my ($Name, $Symbol, $LibVersion) = @_;
14563 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014564 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014565 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14566 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014567 {
14568 return $ParamPos;
14569 }
14570 }
14571 return "lost";
14572}
14573
14574sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14575{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014576 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014578 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014579 {
14580 next if($Order eq "backward" and $ParamPos>$MediumPos);
14581 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014582 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14583 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014584 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014585 push(@Positions, $ParamPos);
14586 }
14587 }
14588 return @Positions;
14589}
14590
14591sub getTypeIdByName($$)
14592{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014593 my ($TypeName, $LibVersion) = @_;
14594 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595}
14596
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014597sub diffTypes($$$)
14598{
14599 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14600 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14601 }
14602 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14603 { # skip recursive declarations
14604 return 0;
14605 }
14606
14607 pushType($_[0], $_[1], \@RecurTypes_Diff);
14608 my $Diff = diffTypes_I(@_);
14609 pop(@RecurTypes_Diff);
14610
14611 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14612}
14613
14614sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014615{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014616 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014617
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014618 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14619 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014620
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014621 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14622 { # equal types
14623 return 0;
14624 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014625 if($Type1_Pure{"Name"} eq "void")
14626 { # from void* to something
14627 return 0;
14628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014629 if($Type1_Pure{"Name"}=~/\*/
14630 or $Type2_Pure{"Name"}=~/\*/)
14631 { # compared in detectTypeChange()
14632 return 0;
14633 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014634
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 my %FloatType = map {$_=>1} (
14636 "float",
14637 "double",
14638 "long double"
14639 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014640
14641 my $T1 = $Type1_Pure{"Type"};
14642 my $T2 = $Type2_Pure{"Type"};
14643
14644 if($T1 eq "Struct"
14645 and $T2 eq "Class")
14646 { # compare as data structures
14647 $T2 = "Struct";
14648 }
14649
14650 if($T1 eq "Class"
14651 and $T2 eq "Struct")
14652 { # compare as data structures
14653 $T1 = "Struct";
14654 }
14655
14656 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014657 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014658 if($T1 eq "Intrinsic"
14659 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014660 { # "int" to "enum"
14661 return 0;
14662 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014663 elsif($T2 eq "Intrinsic"
14664 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665 { # "enum" to "int"
14666 return 0;
14667 }
14668 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014669 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014670 # ...
14671 return 1;
14672 }
14673 }
14674 else
14675 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014676 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014677 {
14678 if($FloatType{$Type1_Pure{"Name"}}
14679 or $FloatType{$Type2_Pure{"Name"}})
14680 { # "float" to "double"
14681 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014682 if($Level eq "Source")
14683 { # Safe
14684 return 0;
14685 }
14686 else {
14687 return 1;
14688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014689 }
14690 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014691 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 {
14693 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14694 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014695 if(not @Membs1
14696 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014697 { # private
14698 return 0;
14699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014700 if($#Membs1!=$#Membs2)
14701 { # different number of elements
14702 return 1;
14703 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014704 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014705 {
14706 foreach my $Pos (@Membs1)
14707 { # compare elements by name and value
14708 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14709 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14710 { # different names
14711 return 1;
14712 }
14713 }
14714 }
14715 else
14716 {
14717 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014718 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014719 if($Level eq "Source")
14720 {
14721 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14722 { # different names
14723 return 1;
14724 }
14725 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014726
14727 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14728 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14729
14730 if($MT1{"Name"} ne $MT2{"Name"}
14731 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14732 {
14733 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14734 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14735
14736 if($PL1 ne $PL2)
14737 { # different pointer level
14738 return 1;
14739 }
14740
14741 # compare base types
14742 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14743 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14744
14745 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14746 { # different types
14747 return 1;
14748 }
14749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014750 }
14751 }
14752 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014753 else
14754 {
14755 # TODO: arrays, etc.
14756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014757 }
14758 return 0;
14759}
14760
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014761sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014762{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014763 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014764 if(not $Type1_Id or not $Type2_Id) {
14765 return ();
14766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014767 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014768 my %Type1 = get_Type($Type1_Id, 1);
14769 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014770 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14771 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014772
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014773 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14774 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 +040014775
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014776 if(defined $UsedDump{1}{"DWARF"})
14777 {
14778 if($Type1_Pure{"Name"} eq "__unknown__"
14779 or $Type2_Pure{"Name"} eq "__unknown__"
14780 or $Type1_Base{"Name"} eq "__unknown__"
14781 or $Type2_Base{"Name"} eq "__unknown__")
14782 { # Error ABI dump
14783 return ();
14784 }
14785 }
14786
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014787 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14788 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014789 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14790 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14791 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14792 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14793 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14794 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14795 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014796 if($Type1{"Name"} eq $Type2{"Name"})
14797 {
14798 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14799 { # will be reported in mergeTypes() as typedef problem
14800 return ();
14801 }
14802 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14803 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14804 if(%Typedef_1 and %Typedef_2)
14805 {
14806 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14807 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14808 { # const Typedef
14809 return ();
14810 }
14811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014812 }
14813 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14814 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014815 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014816 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14817 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014818 {
14819 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14820 "Old_Value"=>$Type1_Base{"Name"},
14821 "New_Value"=>$Type2_Base{"Name"},
14822 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014823 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014824 }
14825 else
14826 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014827 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014828 { # format change
14829 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14830 "Old_Value"=>$Type1_Base{"Name"},
14831 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014832 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014833 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014834 }
14835 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14836 {
14837 %{$LocalProblems{$Prefix."_BaseType"}}=(
14838 "Old_Value"=>$Type1_Base{"Name"},
14839 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014840 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014841 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014842 }
14843 }
14844 }
14845 }
14846 elsif($Type1{"Name"} ne $Type2{"Name"})
14847 { # type change
14848 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14849 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014850 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014851 and $Type1_Pure{"Name"} eq "void")
14852 {
14853 %{$LocalProblems{"Return_Type_From_Void"}}=(
14854 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014855 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014857 elsif($Prefix eq "Return"
14858 and $Type2_Pure{"Name"} eq "void")
14859 {
14860 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14861 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014862 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014864 else
14865 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014866 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014867 and $Type1{"Size"} and $Type2{"Size"}
14868 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014869 {
14870 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14871 "Old_Value"=>$Type1{"Name"},
14872 "New_Value"=>$Type2{"Name"},
14873 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014874 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014875 }
14876 else
14877 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014878 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014879 { # format change
14880 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14881 "Old_Value"=>$Type1{"Name"},
14882 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014883 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014884 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014885 }
14886 elsif(tNameLock($Type1_Id, $Type2_Id))
14887 { # FIXME: correct this condition
14888 %{$LocalProblems{$Prefix."_Type"}}=(
14889 "Old_Value"=>$Type1{"Name"},
14890 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014891 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014892 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014893 }
14894 }
14895 }
14896 }
14897 }
14898 if($Type1_PLevel!=$Type2_PLevel)
14899 {
14900 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14901 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14902 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014903 if($Level eq "Source")
14904 {
14905 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014906 "Old_Value"=>$Type1_PLevel,
14907 "New_Value"=>$Type2_PLevel);
14908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014909 else
14910 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014911 if($Type2_PLevel>$Type1_PLevel)
14912 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014913 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14914 "Old_Value"=>$Type1_PLevel,
14915 "New_Value"=>$Type2_PLevel);
14916 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014917 else
14918 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014919 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14920 "Old_Value"=>$Type1_PLevel,
14921 "New_Value"=>$Type2_PLevel);
14922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014923 }
14924 }
14925 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014926 if($Type1_Pure{"Type"} eq "Array"
14927 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014928 { # base_type[N] -> base_type[N]
14929 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014930 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014931 foreach my $SubProblemType (keys(%SubProblems))
14932 {
14933 $SubProblemType=~s/_Type/_BaseType/g;
14934 next if(defined $LocalProblems{$SubProblemType});
14935 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14936 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14937 }
14938 }
14939 }
14940 return %LocalProblems;
14941}
14942
14943sub tNameLock($$)
14944{
14945 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014946 my $Changed = 0;
14947 if(differentDumps("G"))
14948 { # different GCC versions
14949 $Changed = 1;
14950 }
14951 elsif(differentDumps("V"))
14952 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014953 if(not checkDump(1, "2.20")
14954 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014955 { # latest names update
14956 # 2.6: added restrict qualifier
14957 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014958 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014959 $Changed = 1;
14960 }
14961 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014962
14963 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14964 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14965
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014966 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14967 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14968
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014969 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014971 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014972 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014973 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014974 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014975 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014976 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014977 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014978 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014979 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14980 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14981 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014982 { # equal base types
14983 return 0;
14984 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014985
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014986 if(not checkDump(1, "2.13")
14987 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014988 { # broken array names in ABI dumps < 2.13
14989 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014990 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014991 return 0;
14992 }
14993 }
14994
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014995 if(not checkDump(1, "2.6")
14996 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014997 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014998 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014999 and $TN2=~/\brestrict\b/) {
15000 return 0;
15001 }
15002 }
15003
15004 if(not checkDump(1, "2.20")
15005 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015006 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015007 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15008 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015009 return 0;
15010 }
15011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015012 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015013 else
15014 {
15015 # typedef struct {...} type_t
15016 # typedef struct type_t {...} type_t
15017 if(index($TN1, " ".$TN2)!=-1)
15018 {
15019 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15020 return 0;
15021 }
15022 }
15023 if(index($TN2, " ".$TN1)!=-1)
15024 {
15025 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15026 return 0;
15027 }
15028 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015029
15030 if($TT1 eq "FuncPtr"
15031 and $TT2 eq "FuncPtr")
15032 {
15033 my $TN1_C = $TN1;
15034 my $TN2_C = $TN2;
15035
15036 $TN1_C=~s/\b(struct|union) //g;
15037 $TN2_C=~s/\b(struct|union) //g;
15038
15039 if($TN1_C eq $TN2_C) {
15040 return 0;
15041 }
15042 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015043 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015044
15045 my ($N1, $N2) = ($TN1, $TN2);
15046 $N1=~s/\b(struct|union) //g;
15047 $N2=~s/\b(struct|union) //g;
15048
15049 if($N1 eq $N2)
15050 { # QList<struct QUrl> and QList<QUrl>
15051 return 0;
15052 }
15053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015054 return 1;
15055}
15056
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015057sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015059 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015060 if(defined $Cache{"differentDumps"}{$Check}) {
15061 return $Cache{"differentDumps"}{$Check};
15062 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015063 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015064 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015065 if($Check eq "G")
15066 {
15067 if(getGccVersion(1) ne getGccVersion(2))
15068 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015069 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015070 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015071 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015072 if($Check eq "V")
15073 {
15074 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15075 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15076 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015077 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015080 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015081 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015082}
15083
15084sub formatVersion($$)
15085{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015086 my ($V, $Digits) = @_;
15087 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015088 return join(".", splice(@Elems, 0, $Digits));
15089}
15090
15091sub htmlSpecChars($)
15092{
15093 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015094 if(not $Str) {
15095 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015097 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15098 $Str=~s/</&lt;/g;
15099 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15100 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015101 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15102 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015103 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015104 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015105 $Str=~s/\n/<br\/>/g;
15106 $Str=~s/\"/&quot;/g;
15107 $Str=~s/\'/&#39;/g;
15108 return $Str;
15109}
15110
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015111sub xmlSpecChars($)
15112{
15113 my $Str = $_[0];
15114 if(not $Str) {
15115 return $Str;
15116 }
15117
15118 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15119 $Str=~s/</&lt;/g;
15120 $Str=~s/>/&gt;/g;
15121
15122 $Str=~s/\"/&quot;/g;
15123 $Str=~s/\'/&#39;/g;
15124
15125 return $Str;
15126}
15127
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015128sub xmlSpecChars_R($)
15129{
15130 my $Str = $_[0];
15131 if(not $Str) {
15132 return $Str;
15133 }
15134
15135 $Str=~s/&amp;/&/g;
15136 $Str=~s/&lt;/</g;
15137 $Str=~s/&gt;/>/g;
15138
15139 $Str=~s/&quot;/"/g;
15140 $Str=~s/&#39;/'/g;
15141
15142 return $Str;
15143}
15144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015145sub black_name($)
15146{
15147 my $Name = $_[0];
15148 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15149}
15150
15151sub highLight_Signature($)
15152{
15153 my $Signature = $_[0];
15154 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15155}
15156
15157sub highLight_Signature_Italic_Color($)
15158{
15159 my $Signature = $_[0];
15160 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15161}
15162
15163sub separate_symbol($)
15164{
15165 my $Symbol = $_[0];
15166 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15167 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15168 ($Name, $Spec, $Ver) = ($1, $2, $3);
15169 }
15170 return ($Name, $Spec, $Ver);
15171}
15172
15173sub cut_f_attrs($)
15174{
15175 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15176 return $2;
15177 }
15178 return "";
15179}
15180
15181sub highLight_Signature_PPos_Italic($$$$$)
15182{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015183 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15184 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015185 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15186 my $Return = "";
15187 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15188 $Return = $2;
15189 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015190 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015191 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015192 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015193 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015194 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015195 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015196 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015197 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015198 }
15199 return $Signature;
15200 }
15201 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15202 $Begin.=" " if($Begin!~/ \Z/);
15203 $End = cut_f_attrs($Signature);
15204 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015205 my ($Short, $Params) = split_Signature($Signature);
15206 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015207 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015208 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015209 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015210 $Part=~s/\A\s+|\s+\Z//g;
15211 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15212 if($Part=~/\([\*]+(\w+)\)/i) {
15213 $ParamName = $1;#func-ptr
15214 }
15215 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15216 $ParamName = $1;
15217 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015218 if(not $ParamName)
15219 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015220 push(@Parts, $Part_Styled);
15221 next;
15222 }
15223 if($ItalicParams and not $TName_Tid{1}{$Part}
15224 and not $TName_Tid{2}{$Part})
15225 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015226 my $Style = "<i>$ParamName</i>";
15227
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015228 if($Param_Pos ne ""
15229 and $Pos==$Param_Pos) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015230 $Style = "<span class=\'fp\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231 }
15232 elsif($ColorParams) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015233 $Style = "<span class=\'color_p\'>$ParamName</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030015235
15236 $Part_Styled=~s!(\W)$ParamName([\,\)]|\Z)!$1$Style$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 }
15238 $Part_Styled=~s/,(\w)/, $1/g;
15239 push(@Parts, $Part_Styled);
15240 }
15241 if(@Parts)
15242 {
15243 foreach my $Num (0 .. $#Parts)
15244 {
15245 if($Num==$#Parts)
15246 { # add ")" to the last parameter
15247 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15248 }
15249 elsif(length($Parts[$Num])<=45) {
15250 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15251 }
15252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015253 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015254 }
15255 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015256 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015257 }
15258 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015259 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015260 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015261 $Signature=~s!\[\]![&#160;]!g;
15262 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015263 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15264 if($SymbolVersion) {
15265 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15266 }
15267 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268}
15269
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015270sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015272 my $Signature = $_[0];
15273 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15274 {
15275 $Signature=~s/\A\Q$ShortName\E\(//g;
15276 cut_f_attrs($Signature);
15277 $Signature=~s/\)\Z//;
15278 return ($ShortName, $Signature);
15279 }
15280
15281 # error
15282 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015283}
15284
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015285sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015286{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015287 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015288 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015289 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15290 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291 foreach my $Pos (0 .. length($Params) - 1)
15292 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015293 my $S = substr($Params, $Pos, 1);
15294 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015295 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015296 }
15297 if($S eq "," and
15298 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015299 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015300 if($Comma)
15301 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015302 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015304 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015305 }
15306 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015307 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015308 }
15309 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015310 if(not $Sp)
15311 { # remove spaces
15312 foreach (@Parts)
15313 {
15314 s/\A //g;
15315 s/ \Z//g;
15316 }
15317 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015318 return @Parts;
15319}
15320
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015321sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322{
15323 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015324 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015325 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015326 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15327 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015328 $Center+=length($1);
15329 }
15330 foreach my $Pos (0 .. length($Sign)-1)
15331 {
15332 my $S = substr($Sign, $Pos, 1);
15333 if($S eq $Target)
15334 {
15335 if($B{"("}==$B{")"}
15336 and $B{"<"}==$B{">"}) {
15337 return $Center;
15338 }
15339 }
15340 if(defined $B{$S}) {
15341 $B{$S}+=1;
15342 }
15343 $Center+=1;
15344 }
15345 return 0;
15346}
15347
15348sub appendFile($$)
15349{
15350 my ($Path, $Content) = @_;
15351 return if(not $Path);
15352 if(my $Dir = get_dirname($Path)) {
15353 mkpath($Dir);
15354 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015355 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015356 print FILE $Content;
15357 close(FILE);
15358}
15359
15360sub writeFile($$)
15361{
15362 my ($Path, $Content) = @_;
15363 return if(not $Path);
15364 if(my $Dir = get_dirname($Path)) {
15365 mkpath($Dir);
15366 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015367 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368 print FILE $Content;
15369 close(FILE);
15370}
15371
15372sub readFile($)
15373{
15374 my $Path = $_[0];
15375 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015376 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015377 local $/ = undef;
15378 my $Content = <FILE>;
15379 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015380 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015381 $Content=~s/\r/\n/g;
15382 }
15383 return $Content;
15384}
15385
15386sub get_filename($)
15387{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015388 if(defined $Cache{"get_filename"}{$_[0]}) {
15389 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015390 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015391 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15392 return ($Cache{"get_filename"}{$_[0]}=$1);
15393 }
15394 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015395}
15396
15397sub get_dirname($)
15398{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015399 if(defined $Cache{"get_dirname"}{$_[0]}) {
15400 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015401 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015402 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15403 return ($Cache{"get_dirname"}{$_[0]}=$1);
15404 }
15405 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406}
15407
15408sub separate_path($) {
15409 return (get_dirname($_[0]), get_filename($_[0]));
15410}
15411
15412sub esc($)
15413{
15414 my $Str = $_[0];
15415 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15416 return $Str;
15417}
15418
15419sub readLineNum($$)
15420{
15421 my ($Path, $Num) = @_;
15422 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015423 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015424 foreach (1 ... $Num) {
15425 <FILE>;
15426 }
15427 my $Line = <FILE>;
15428 close(FILE);
15429 return $Line;
15430}
15431
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015432sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015433{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015434 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015435 return () if(not $Path or not -f $Path);
15436 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015437 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15438 {
15439 foreach my $AttrVal (split(/;/, $1))
15440 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015441 if($AttrVal=~/(.+):(.+)/)
15442 {
15443 my ($Name, $Value) = ($1, $2);
15444 $Attributes{$Name} = $Value;
15445 }
15446 }
15447 }
15448 return \%Attributes;
15449}
15450
15451sub is_abs($) {
15452 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15453}
15454
15455sub get_abs_path($)
15456{ # abs_path() should NOT be called for absolute inputs
15457 # because it can change them
15458 my $Path = $_[0];
15459 if(not is_abs($Path)) {
15460 $Path = abs_path($Path);
15461 }
15462 return $Path;
15463}
15464
15465sub get_OSgroup()
15466{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015467 my $N = $Config{"osname"};
15468 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015469 return "macos";
15470 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015471 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015472 return "bsd";
15473 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015474 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 return "beos";
15476 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015477 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 return "symbian";
15479 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015480 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481 return "windows";
15482 }
15483 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015484 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015485 }
15486}
15487
15488sub getGccVersion($)
15489{
15490 my $LibVersion = $_[0];
15491 if($GCC_VERSION{$LibVersion})
15492 { # dump version
15493 return $GCC_VERSION{$LibVersion};
15494 }
15495 elsif($UsedDump{$LibVersion}{"V"})
15496 { # old-version dumps
15497 return "unknown";
15498 }
15499 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15500 if(not $GccVersion) {
15501 return "unknown";
15502 }
15503 return $GccVersion;
15504}
15505
15506sub showArch($)
15507{
15508 my $Arch = $_[0];
15509 if($Arch eq "arm"
15510 or $Arch eq "mips") {
15511 return uc($Arch);
15512 }
15513 return $Arch;
15514}
15515
15516sub getArch($)
15517{
15518 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015519
15520 if($TargetArch) {
15521 return $TargetArch;
15522 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015523 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015524 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525 return $CPU_ARCH{$LibVersion};
15526 }
15527 elsif($UsedDump{$LibVersion}{"V"})
15528 { # old-version dumps
15529 return "unknown";
15530 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015531
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015532 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015533}
15534
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015535sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015536{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015537 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015538
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015540 if(getArch(1) ne getArch(2)
15541 or getArch(1) eq "unknown"
15542 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015543 { # don't show architecture in the header
15544 $ArchInfo="";
15545 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015546 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015547 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015548 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015549 }
15550 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015551 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015552 }
15553 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015554 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015555 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015556
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015557 my $V1 = $Descriptor{1}{"Version"};
15558 my $V2 = $Descriptor{2}{"Version"};
15559
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015560 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15561 {
15562 my $M1 = $UsedDump{1}{"M"};
15563 my $M2 = $UsedDump{2}{"M"};
15564
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015565 my $M1S = $M1;
15566 my $M2S = $M2;
15567
15568 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15569 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15570
15571 if($M1S eq $M2S
15572 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015573 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015574 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15575 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015576 }
15577 else
15578 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015579 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15580 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015581 }
15582 }
15583 else
15584 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015585 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015586 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015587 }
15588
15589 $Title .= $ArchInfo;
15590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015591 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015592 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015594 $Title = "<h1>".$Title."</h1>\n";
15595 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596}
15597
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015598sub get_CheckedHeaders($)
15599{
15600 my $LibVersion = $_[0];
15601
15602 my @Headers = ();
15603
15604 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15605 {
15606 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015607
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015608 if(not is_target_header($File, $LibVersion)) {
15609 next;
15610 }
15611
15612 if(skipHeader($File, $LibVersion)) {
15613 next;
15614 }
15615
15616 push(@Headers, $Path);
15617 }
15618
15619 return @Headers;
15620}
15621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015622sub get_SourceInfo()
15623{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015624 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015625
15626 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015628 $CheckedHeaders = "<a name='Headers'></a>";
15629 if($OldStyle) {
15630 $CheckedHeaders .= "<h2>Header Files (".($#Headers+1).")</h2>";
15631 }
15632 else {
15633 $CheckedHeaders .= "<h2>Header Files <span class='gray'>&nbsp;".($#Headers+1)."&nbsp;</span></h2>";
15634 }
15635 $CheckedHeaders .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015636 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 +040015637 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015638 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15639 my $Name = get_filename($Identity);
15640 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15641 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015642 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015643 $CheckedHeaders .= "</div>\n";
15644 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015645 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015646
15647 if(my @Sources = keys(%{$Registered_Sources{1}}))
15648 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015649 $CheckedSources = "<a name='Sources'></a>";
15650 if($OldStyle) {
15651 $CheckedSources .= "<h2>Source Files (".($#Sources+1).")</h2>";
15652 }
15653 else {
15654 $CheckedSources .= "<h2>Source Files <span class='gray'>&nbsp;".($#Sources+1)."&nbsp;</span></h2>";
15655 }
15656 $CheckedSources .= "<hr/>\n<div class='h_list'>\n";
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015657 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15658 {
15659 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15660 my $Name = get_filename($Identity);
15661 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15662 $CheckedSources .= $Name.$Comment."<br/>\n";
15663 }
15664 $CheckedSources .= "</div>\n";
15665 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15666 }
15667
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015668 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015669 {
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030015670 $CheckedLibs = "<a name='Libs'></a>";
15671 if($OldStyle) {
15672 $CheckedLibs .= "<h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2>";
15673 }
15674 else {
15675 $CheckedLibs .= "<h2>".get_ObjTitle()." <span class='gray'>&nbsp;".keys(%{$Library_Symbol{1}})."&nbsp;</span></h2>";
15676 }
15677 $CheckedLibs .= "<hr/>\n<div class='lib_list'>\n";
15678 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}})) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015679 $CheckedLibs .= $Library."<br/>\n";
15680 }
15681 $CheckedLibs .= "</div>\n";
15682 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015683 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015684
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015685 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15686}
15687
15688sub get_ObjTitle()
15689{
15690 if(defined $UsedDump{1}{"DWARF"}) {
15691 return "Objects";
15692 }
15693 else {
15694 return ucfirst($SLIB_TYPE)." Libraries";
15695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696}
15697
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015698sub get_TypeProblems_Count($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015699{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015700 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015701 my $Type_Problems_Count = 0;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015702
15703 foreach my $Type_Name (sort keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015704 {
15705 my %Kinds_Target = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015706 foreach my $Kind (keys(%{$TypeChanges{$Level}{$Type_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015707 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015708 foreach my $Location (keys(%{$TypeChanges{$Level}{$Type_Name}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015709 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015710 my $Target = $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015711 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015712
15713 if($Severity ne $TargetSeverity) {
15714 next;
15715 }
15716
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015717 if($Kinds_Target{$Kind}{$Target}) {
15718 next;
15719 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015720
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015721 $Kinds_Target{$Kind}{$Target} = 1;
15722 $Type_Problems_Count += 1;
15723 }
15724 }
15725 }
15726 return $Type_Problems_Count;
15727}
15728
15729sub get_Summary($)
15730{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015731 my $Level = $_[0];
15732 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015733 $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 +040015734 %{$RESULT{$Level}} = (
15735 "Problems"=>0,
15736 "Warnings"=>0,
15737 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015739 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015740 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015741 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015742 {
15743 if(not defined $CompatRules{$Level}{$Kind})
15744 { # unknown rule
15745 if(not $UnknownRules{$Level}{$Kind})
15746 { # only one warning
15747 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15748 $UnknownRules{$Level}{$Kind}=1;
15749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015750 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015751 }
15752 }
15753 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015754 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15755 {
15756 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15757 {
15758 if(not defined $CompatRules{$Level}{$Kind})
15759 { # unknown rule
15760 if(not $UnknownRules{$Level}{$Kind})
15761 { # only one warning
15762 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15763 $UnknownRules{$Level}{$Kind}=1;
15764 }
15765 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15766 }
15767 }
15768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015769 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015771 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772 {
15773 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15774 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015775 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015776 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015777 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015778 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015779 $Added += 1;
15780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015781 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 {
15783 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015784 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785 }
15786 else
15787 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015788 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015789 $I_Other += 1;
15790 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015791 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015792 $I_Problems_High += 1;
15793 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015794 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015795 $I_Problems_Medium += 1;
15796 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015797 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015798 $I_Problems_Low += 1;
15799 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015800 if(($Severity ne "Low" or $StrictCompat)
15801 and $Severity ne "Safe") {
15802 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015803 }
15804 }
15805 }
15806 }
15807 }
15808 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015809
15810 my %MethodTypeIndex = ();
15811
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015812 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015813 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015814 my @Kinds = sort keys(%{$CompatProblems{$Level}{$Interface}});
15815 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015816 {
15817 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15818 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015819 my @Locs = sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}});
15820 foreach my $Location (@Locs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015821 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015822 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15823 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015824
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015825 if(defined $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target})
15826 { # one location for one type and target
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 next;
15828 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015829 $MethodTypeIndex{$Interface}{$Type_Name}{$Kind}{$Target} = 1;
15830 $TypeChanges{$Level}{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15831
15832 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015833
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015834 if(($Severity ne "Low" or $StrictCompat)
15835 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015836 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015837 if(my $Sev = $TotalAffected{$Level}{$Interface})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015838 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015839 if($Severity_Val{$Severity}>$Severity_Val{$Sev}) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015840 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015841 }
15842 }
15843 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015844 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015847 }
15848 }
15849 }
15850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015851
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030015852 $T_Problems_High = get_TypeProblems_Count("High", $Level);
15853 $T_Problems_Medium = get_TypeProblems_Count("Medium", $Level);
15854 $T_Problems_Low = get_TypeProblems_Count("Low", $Level);
15855 $T_Other = get_TypeProblems_Count("Safe", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015856
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015857 # changed and removed public symbols
15858 my $SCount = keys(%{$CheckedSymbols{$Level}});
15859 if($ExtendedCheck)
15860 { # don't count external_func_0 for constants
15861 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015863 if($SCount)
15864 {
15865 my %Weight = (
15866 "High" => 100,
15867 "Medium" => 50,
15868 "Low" => 25
15869 );
15870 foreach (keys(%{$TotalAffected{$Level}})) {
15871 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015873 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015874 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015875 else {
15876 $RESULT{$Level}{"Affected"} = 0;
15877 }
15878
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015879 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15880 if($RESULT{$Level}{"Affected"}>=100) {
15881 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882 }
15883
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015884 $RESULT{$Level}{"Problems"} += $Removed;
15885 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015887 if($StrictCompat) {
15888 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15889 }
15890 else {
15891 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015893
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015894 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015895 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015896 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015897 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015898 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015899 if($Severity eq "Safe")
15900 {
15901 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015902 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015903 elsif($Severity eq "Low")
15904 {
15905 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015907 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015908 }
15909
15910 if($C_Problems_Low)
15911 {
15912 if($StrictCompat) {
15913 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15914 }
15915 else {
15916 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015917 }
15918 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015919 if($RESULT{$Level}{"Problems"}
15920 and $RESULT{$Level}{"Affected"}) {
15921 $RESULT{$Level}{"Verdict"} = "incompatible";
15922 }
15923 else {
15924 $RESULT{$Level}{"Verdict"} = "compatible";
15925 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015926
15927 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15928 if(not $TotalTypes)
15929 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015930 $TotalTypes = keys(%{$TName_Tid{1}});
15931 }
15932
15933 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15934 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15935
15936 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15937
15938 if($ReportFormat eq "xml")
15939 { # XML
15940 # test info
15941 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15942 $TestInfo .= " <version1>\n";
15943 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015944 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15946 $TestInfo .= " </version1>\n";
15947
15948 $TestInfo .= " <version2>\n";
15949 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015950 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015951 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15952 $TestInfo .= " </version2>\n";
15953 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15954
15955 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015956 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015957 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015958 $TestResults .= " <headers>\n";
15959 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15960 {
15961 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15962 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15963 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15964 }
15965 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015966 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015967
15968 if(my @Sources = keys(%{$Registered_Sources{1}}))
15969 {
15970 $TestResults .= " <sources>\n";
15971 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15972 {
15973 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15974 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15975 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15976 }
15977 $TestResults .= " </sources>\n";
15978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979
15980 $TestResults .= " <libs>\n";
15981 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15982 {
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030015983 # $Library .= " (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015984 $TestResults .= " <name>$Library</name>\n";
15985 }
15986 $TestResults .= " </libs>\n";
15987
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015988 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015989 $TestResults .= " <types>".$TotalTypes."</types>\n";
15990
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015991 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15992 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15994
15995 # problem summary
15996 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15997 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15998
15999 $Problem_Summary .= " <problems_with_types>\n";
16000 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16001 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16002 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16003 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16004 $Problem_Summary .= " </problems_with_types>\n";
16005
16006 $Problem_Summary .= " <problems_with_symbols>\n";
16007 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16008 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16009 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016010 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016011 $Problem_Summary .= " </problems_with_symbols>\n";
16012
16013 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016016
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016017 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16018
16019 return ($TestInfo.$TestResults.$Problem_Summary, "");
16020 }
16021 else
16022 { # HTML
16023 # test info
16024 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016025 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016026
16027 if($TargetComponent eq "library") {
16028 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
16029 }
16030 else {
16031 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
16032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016033
16034 my (@VInf1, @VInf2, $AddTestInfo) = ();
16035 if($Arch1 ne "unknown"
16036 and $Arch2 ne "unknown")
16037 { # CPU arch
16038 if($Arch1 eq $Arch2)
16039 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016040 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016041 }
16042 else
16043 { # go to the version number
16044 push(@VInf1, showArch($Arch1));
16045 push(@VInf2, showArch($Arch2));
16046 }
16047 }
16048 if($GccV1 ne "unknown"
16049 and $GccV2 ne "unknown"
16050 and $OStarget ne "windows")
16051 { # GCC version
16052 if($GccV1 eq $GccV2)
16053 { # go to the separate section
16054 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16055 }
16056 else
16057 { # go to the version number
16058 push(@VInf1, "gcc ".$GccV1);
16059 push(@VInf2, "gcc ".$GccV2);
16060 }
16061 }
16062 # show long version names with GCC version and CPU architecture name (if different)
16063 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16064 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16065 $TestInfo .= $AddTestInfo;
16066 #if($COMMON_LANGUAGE{1}) {
16067 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16068 #}
16069 if($ExtendedCheck) {
16070 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16071 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016072 if($JoinReport)
16073 {
16074 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016075 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016076 }
16077 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016078 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016079 }
16080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016081 $TestInfo .= "</table>\n";
16082
16083 # test results
16084 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016085 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016086
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030016087 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016088 {
16089 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16090 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16091 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016092
16093 if(my @Sources = keys(%{$Registered_Sources{1}}))
16094 {
16095 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16096 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16097 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016098
16099 if(not $ExtendedCheck)
16100 {
16101 my $Libs_Link = "0";
16102 $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 +040016103 $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 +040016104 }
16105
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016106 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016107
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016108 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016109 if($JoinReport) {
16110 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16111 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016112
Andrey Ponomarenkoce360372016-06-21 19:17:17 +030016113 my $BC_Rate = show_number(100 - $RESULT{$Level}{"Affected"});
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016114
16115 $TestResults .= "<tr><th>Compatibility</th>\n";
16116 if($RESULT{$Level}{"Verdict"} eq "incompatible")
16117 {
16118 my $Cl = "incompatible";
16119 if($BC_Rate>=90) {
16120 $Cl = "warning";
16121 }
16122 elsif($BC_Rate>=80) {
16123 $Cl = "almost_compatible";
16124 }
16125
16126 $TestResults .= "<td class=\'$Cl\'>".$BC_Rate."%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016127 }
16128 else {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016129 $TestResults .= "<td class=\'compatible\'>100%</td>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016130 }
16131 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 $TestResults .= "</table>\n";
16133
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016134 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016135 # problem summary
16136 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016137 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016138 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16139
16140 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016141 if($Added>0)
16142 {
16143 if($JoinReport) {
16144 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16145 }
16146 else {
16147 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16148 }
16149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016150 $META_DATA .= "added:$Added;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016151 $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 +040016152
16153 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016154 if($Removed>0)
16155 {
16156 if($JoinReport) {
16157 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16158 }
16159 else {
16160 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16161 }
16162 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016163 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016164 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016165 $Problem_Summary .= "<td>High</td><td".getStyle("I", "Removed", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016166
16167 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016168 $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 +040016169 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016170 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016171 $Problem_Summary .= "<td>High</td><td".getStyle("T", "High", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016172
16173 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016174 $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 +040016175 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016176 $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 +040016177
16178 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016179 $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 +040016180 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016181 $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 +040016182
16183 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 $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 +040016185 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016186 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016187 $Problem_Summary .= "<td>High</td><td".getStyle("I", "High", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016188
16189 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016190 $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 +040016191 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016192 $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 +040016193
16194 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016195 $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 +040016196 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016197 $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 +040016198
16199 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016200 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16201 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016203 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016204 $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 +040016205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016206 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016207 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016208 {
16209 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016210 $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 +030016211 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016212 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016213
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016214 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016215 {
16216 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016217 $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 +030016218 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016220
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016221 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016222 {
16223 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016224 $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 +030016225 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016226 }
16227
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016228 $META_DATA .= "tool_version:$TOOL_VERSION";
16229 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016231 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16232 }
16233}
16234
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016235sub getStyle($$$)
16236{
16237 my ($Subj, $Act, $Num) = @_;
16238 my %Style = (
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016239 "Added"=>"new",
16240 "Removed"=>"failed",
16241 "Safe"=>"passed",
16242 "Low"=>"warning",
16243 "Medium"=>"failed",
16244 "High"=>"failed"
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016245 );
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016246
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016247 if($Num>0) {
16248 return " class='".$Style{$Act}."'";
16249 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016250
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016251 return "";
16252}
16253
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016254sub show_number($)
16255{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016256 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016257 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016258 my $Num = cut_off_number($_[0], 2, 0);
16259 if($Num eq "0")
16260 {
16261 foreach my $P (3 .. 7)
16262 {
16263 $Num = cut_off_number($_[0], $P, 1);
16264 if($Num ne "0") {
16265 last;
16266 }
16267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 }
16269 if($Num eq "0") {
16270 $Num = $_[0];
16271 }
16272 return $Num;
16273 }
16274 return $_[0];
16275}
16276
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016277sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016278{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016279 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 if($num!~/\./)
16281 {
16282 $num .= ".";
16283 foreach (1 .. $digs_to_cut-1) {
16284 $num .= "0";
16285 }
16286 }
16287 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16288 {
16289 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16290 $num .= "0";
16291 }
16292 }
16293 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16294 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16295 }
16296 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016297 if($z) {
16298 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016300 return $num;
16301}
16302
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016303sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016304{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016305 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016306 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016307
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016308 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016309 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16310 {
16311 my $Header = $Constants{1}{$Constant}{"Header"};
16312 if(not $Header)
16313 { # added
16314 $Header = $Constants{2}{$Constant}{"Header"}
16315 }
16316
16317 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16318 {
16319 if(not defined $CompatRules{$Level}{$Kind}) {
16320 next;
16321 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016322 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016323 next;
16324 }
16325 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016328
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 if($ReportFormat eq "xml")
16330 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016331 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016332 {
16333 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016334 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016335 {
16336 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016337 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16338 {
16339 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16340 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16341 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016342
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016343 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16344 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16345 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016346 if($Overcome) {
16347 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16348 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016349 $CHANGED_CONSTANTS .= " </problem>\n";
16350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016351 $CHANGED_CONSTANTS .= " </constant>\n";
16352 }
16353 $CHANGED_CONSTANTS .= " </header>\n";
16354 }
16355 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16356 }
16357 else
16358 { # HTML
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016359 my $ProblemsNum = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016360 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 {
16362 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016363 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016365 my $Report = "";
16366
16367 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16368 {
16369 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16370 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016371 $Report .= "<tr>\n<th>1</th>\n<td>".$Change."</td>\n<td>$Effect</td>\n</tr>\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016372 $ProblemsNum += 1;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016373 }
16374 if($Report)
16375 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016376 $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 +030016377 $Report = $ContentSpanStart."<span class='ext'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016378 $Report = insertIDs($Report);
16379 }
16380 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016381 }
16382 $CHANGED_CONSTANTS .= "<br/>\n";
16383 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016384 if($CHANGED_CONSTANTS)
16385 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016386 my $Title = "Problems with Constants, $TargetSeverity Severity";
16387 if($TargetSeverity eq "Safe")
16388 { # Safe Changes
16389 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016390 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016391 if($OldStyle) {
16392 $CHANGED_CONSTANTS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$CHANGED_CONSTANTS;
16393 }
16394 else {
16395 $CHANGED_CONSTANTS = "<h2>$Title <span".getStyle("C", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$CHANGED_CONSTANTS;
16396 }
16397 $CHANGED_CONSTANTS = "<a name='".get_Anchor("Constant", $Level, $TargetSeverity)."'></a>\n".$CHANGED_CONSTANTS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016398 }
16399 }
16400 return $CHANGED_CONSTANTS;
16401}
16402
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016403sub getTitle($$$)
16404{
16405 my ($Header, $Library, $NameSpace) = @_;
16406 my $Title = "";
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030016407
16408 # if($Library and $Library!~/\.\w+\Z/) {
16409 # $Library .= " (.$LIB_EXT)";
16410 # }
16411
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016412 if($Header and $Library)
16413 {
16414 $Title .= "<span class='h_name'>$Header</span>";
16415 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16416 }
16417 elsif($Library) {
16418 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16419 }
16420 elsif($Header) {
16421 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16422 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016423
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016424 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016425 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016426 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016427
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016428 return $Title;
16429}
16430
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016431sub get_Report_Added($)
16432{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016433 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016434 my $ADDED_INTERFACES = "";
16435 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016436 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016437 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016438 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016439 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 {
16442 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16443 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016444 if($Level eq "Source" and $ReportFormat eq "html")
16445 { # do not show library name in HTML report
16446 $DyLib = "";
16447 }
16448 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 }
16450 }
16451 }
16452 if($ReportFormat eq "xml")
16453 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
16456 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016457 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016458 {
16459 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016460 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16462 }
16463 $ADDED_INTERFACES .= " </library>\n";
16464 }
16465 $ADDED_INTERFACES .= " </header>\n";
16466 }
16467 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16468 }
16469 else
16470 { # HTML
16471 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016472 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016474 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016475 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 my %NameSpaceSymbols = ();
16477 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016478 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016479 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016482 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16483 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 foreach my $Interface (@SortedInterfaces)
16485 {
16486 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 my $Signature = get_Signature($Interface, 2);
16488 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016489 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016491 if($Interface=~/\A(_Z|\?)/)
16492 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016493 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016494 $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 +040016495 }
16496 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016497 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016498 }
16499 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016500 else
16501 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016502 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016503 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
16505 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016506 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016507 }
16508 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016509 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016510 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016512 }
16513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016514 if($ADDED_INTERFACES)
16515 {
16516 my $Anchor = "<a name='Added'></a>";
16517 if($JoinReport) {
16518 $Anchor = "<a name='".$Level."_Added'></a>";
16519 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016520 if($OldStyle) {
16521 $ADDED_INTERFACES = "<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES;
16522 }
16523 else {
16524 $ADDED_INTERFACES = "<h2>Added Symbols <span".getStyle("I", "Added", $Added_Number).">&nbsp;$Added_Number&nbsp;</span></h2><hr/>\n".$ADDED_INTERFACES;
16525 }
16526 $ADDED_INTERFACES = $Anchor.$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016527 }
16528 }
16529 return $ADDED_INTERFACES;
16530}
16531
16532sub get_Report_Removed($)
16533{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016534 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016535 my $REMOVED_INTERFACES = "";
16536 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016537 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016538 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016539 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016541 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016543 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16544 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 if($Level eq "Source" and $ReportFormat eq "html")
16546 { # do not show library name in HTML report
16547 $DyLib = "";
16548 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016549 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016550 }
16551 }
16552 }
16553 if($ReportFormat eq "xml")
16554 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016555 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556 {
16557 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016558 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016559 {
16560 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016561 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16562 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 }
16564 $REMOVED_INTERFACES .= " </library>\n";
16565 }
16566 $REMOVED_INTERFACES .= " </header>\n";
16567 }
16568 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16569 }
16570 else
16571 { # HTML
16572 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016575 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016576 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 my %NameSpaceSymbols = ();
16578 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016579 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016580 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016581 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016582 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016583 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16584 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016585 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 {
16587 $Removed_Number += 1;
16588 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016589 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016591 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016592 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016593 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016594 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016596 $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 +040016597 }
16598 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016599 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016600 }
16601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016602 else
16603 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016604 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016605 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016606 }
16607 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016608 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016609 }
16610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 }
16612 }
16613 $REMOVED_INTERFACES .= "<br/>\n";
16614 }
16615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016616 if($REMOVED_INTERFACES)
16617 {
16618 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16619 if($JoinReport) {
16620 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16621 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016622 if($OldStyle) {
16623 $REMOVED_INTERFACES = "<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES;
16624 }
16625 else {
16626 $REMOVED_INTERFACES = "<h2>Removed Symbols <span".getStyle("I", "Removed", $Removed_Number).">&nbsp;$Removed_Number&nbsp;</span></h2><hr/>\n".$REMOVED_INTERFACES;
16627 }
16628
16629 $REMOVED_INTERFACES = $Anchor.$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 }
16631 }
16632 return $REMOVED_INTERFACES;
16633}
16634
16635sub getXmlParams($$)
16636{
16637 my ($Content, $Problem) = @_;
16638 return "" if(not $Content or not $Problem);
16639 my %XMLparams = ();
16640 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16641 {
16642 my $Macro = "\@".lc($Attr);
16643 if($Content=~/\Q$Macro\E/) {
16644 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16645 }
16646 }
16647 my @PString = ();
16648 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016649 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 }
16651 if(@PString) {
16652 return " ".join(" ", @PString);
16653 }
16654 else {
16655 return "";
16656 }
16657}
16658
16659sub addMarkup($)
16660{
16661 my $Content = $_[0];
16662 # auto-markup
16663 $Content=~s/\n[ ]*//; # spaces
16664 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16665 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016666 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16668 if($Content=~/\ANOTE:/)
16669 { # notes
16670 $Content=~s!(NOTE):!<b>$1</b>:!g;
16671 }
16672 else {
16673 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16674 }
16675 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16676 my @Keywords = (
16677 "void",
16678 "const",
16679 "static",
16680 "restrict",
16681 "volatile",
16682 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016683 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016684 );
16685 my $MKeys = join("|", @Keywords);
16686 foreach (@Keywords) {
16687 $MKeys .= "|non-".$_;
16688 }
16689 $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 +040016690
16691 # Markdown
16692 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16693 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 return $Content;
16695}
16696
16697sub applyMacroses($$$$)
16698{
16699 my ($Level, $Kind, $Content, $Problem) = @_;
16700 return "" if(not $Content or not $Problem);
16701 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16702 $Content = addMarkup($Content);
16703 # macros
16704 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16705 {
16706 my $Macro = "\@".lc($Attr);
16707 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016708 if(not defined $Value
16709 or $Value eq "") {
16710 next;
16711 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016712
16713 if(index($Content, $Macro)==-1) {
16714 next;
16715 }
16716
16717 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16718 and $Kind!~/_Type_/
16719 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016720 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016721 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016722 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 $Value = black_name($Value);
16724 }
16725 elsif($Value=~/\s/) {
16726 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16727 }
16728 elsif($Value=~/\A\d+\Z/
16729 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16730 { # bits to bytes
16731 if($Value % $BYTE_SIZE)
16732 { # bits
16733 if($Value==1) {
16734 $Value = "<b>".$Value."</b> bit";
16735 }
16736 else {
16737 $Value = "<b>".$Value."</b> bits";
16738 }
16739 }
16740 else
16741 { # bytes
16742 $Value /= $BYTE_SIZE;
16743 if($Value==1) {
16744 $Value = "<b>".$Value."</b> byte";
16745 }
16746 else {
16747 $Value = "<b>".$Value."</b> bytes";
16748 }
16749 }
16750 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016751 else
16752 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016753 $Value = "<b>".htmlSpecChars($Value)."</b>";
16754 }
16755 $Content=~s/\Q$Macro\E/$Value/g;
16756 }
16757
16758 if($Content=~/(\A|[^\@\w])\@\w/)
16759 {
16760 if(not $IncompleteRules{$Level}{$Kind})
16761 { # only one warning
16762 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16763 $IncompleteRules{$Level}{$Kind} = 1;
16764 }
16765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 return $Content;
16767}
16768
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016769sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016770{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016771 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016772 my $INTERFACE_PROBLEMS = "";
16773 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016774
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016775 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016776 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016777 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16778 if($SV and defined $CompatProblems{$Level}{$SN}) {
16779 next;
16780 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016781 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16782 my $DyLib = $Symbol_Library{1}{$Symbol};
16783 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
16784 { # Symbol with Version
16785 $DyLib = $Symbol_Library{1}{$VSym};
16786 }
16787 if(not $DyLib)
16788 { # const global data
16789 $DyLib = "";
16790 }
16791 if($Level eq "Source" and $ReportFormat eq "html")
16792 { # do not show library name in HTML report
16793 $DyLib = "";
16794 }
16795
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016796 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016797 {
16798 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016799 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016800 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016801 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16802 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016803 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016804 if($Severity eq $TargetSeverity)
16805 {
16806 $SymbolChanges{$Symbol}{$Kind} = $CompatProblems{$Level}{$Symbol}{$Kind};
16807 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016808 }
16809 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016810 }
16811 }
16812 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016813
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 if($ReportFormat eq "xml")
16815 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016816 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016817 {
16818 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
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 {
16821 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016822 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16823 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 {
16825 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016826 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016827 {
16828 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16829 {
16830 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016831 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016832
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016833 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16834 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16835 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16836 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16837 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016838 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16839 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016841 $INTERFACE_PROBLEMS .= " </problem>\n";
16842 }
16843 }
16844 $INTERFACE_PROBLEMS .= " </symbol>\n";
16845 }
16846 $INTERFACE_PROBLEMS .= " </library>\n";
16847 }
16848 $INTERFACE_PROBLEMS .= " </header>\n";
16849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016850 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016851 }
16852 else
16853 { # HTML
16854 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016855 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016857 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016858 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016859 my (%NameSpaceSymbols, %NewSignature) = ();
16860 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016861 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016863 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016864 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016865 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016866 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 +040016867 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 my $Signature = get_Signature($Symbol, 1);
16870 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016871 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016872 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016873 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016874 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016876 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016877 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016878 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016880 }
16881 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16882 {
16883 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016884 $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 +040016885 $ProblemNum += 1;
16886 $ProblemsNum += 1;
16887 }
16888 }
16889 }
16890 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016892 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016893 my $ShowSymbol = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 if($Signature) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016895 $ShowSymbol = highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016897
16898 if($NameSpace)
16899 {
16900 $SYMBOL_REPORT = cut_Namespace($SYMBOL_REPORT, $NameSpace);
16901 $ShowSymbol = cut_Namespace($ShowSymbol, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016902 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016903
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016904 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowSymbol;
16905 if($OldStyle) {
16906 $INTERFACE_PROBLEMS .= " ($ProblemNum)";
16907 }
16908 else {
16909 $INTERFACE_PROBLEMS .= " <span".getStyle("I", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
16910 }
16911 $INTERFACE_PROBLEMS .= $ContentSpanEnd."<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016913
16914 if(my $NSign = $NewSignature{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016915 { # argument list changed to
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016916 if($NameSpace) {
16917 $NSign = cut_Namespace($NSign, $NameSpace);
16918 }
16919 $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 +040016920 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016921
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016922 if($Symbol=~/\A(_Z|\?)/) {
16923 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16924 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016925
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016926 $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 +040016927 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016928 }
16929 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016930 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 }
16932 }
16933 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016934
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 if($INTERFACE_PROBLEMS)
16936 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016937 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16938 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16939 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016940 { # Safe Changes
16941 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016942 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030016943 if($OldStyle) {
16944 $INTERFACE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$INTERFACE_PROBLEMS;
16945 }
16946 else {
16947 $INTERFACE_PROBLEMS = "<h2>$Title <span".getStyle("I", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$INTERFACE_PROBLEMS;
16948 }
16949 $INTERFACE_PROBLEMS = "<a name=\'".get_Anchor("Symbol", $Level, $TargetSeverity)."\'></a><a name=\'".get_Anchor("Interface", $Level, $TargetSeverity)."\'></a>\n".$INTERFACE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 }
16951 }
16952 return $INTERFACE_PROBLEMS;
16953}
16954
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030016955sub cut_Namespace($$)
16956{
16957 my ($N, $Ns) = @_;
16958 $N=~s/\b\Q$Ns\E:://g;
16959 return $N;
16960}
16961
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962sub get_Report_TypeProblems($$)
16963{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016964 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016965 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016966
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016967 my %ReportMap = ();
16968 my %TypeChanges_Sev = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016969
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016970 foreach my $TypeName (keys(%{$TypeChanges{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016971 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016972 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
16973
16974 foreach my $Kind (keys(%{$TypeChanges{$Level}{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016975 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016976 foreach my $Location (keys(%{$TypeChanges{$Level}{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016978 my $Target = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016979 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016980
16981 if($Severity eq $TargetSeverity)
16982 {
16983 $ReportMap{$HeaderName}{$TypeName} = 1;
16984 $TypeChanges_Sev{$TypeName}{$Kind}{$Location} = $TypeChanges{$Level}{$TypeName}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016988 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016989
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016990 if($ReportFormat eq "xml")
16991 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016992 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016993 {
16994 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016995 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016996 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016997 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016998 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030016999 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017001 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017003 $Kinds_Locations{$Kind}{$Location} = 1;
17004
17005 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17006 if($Kinds_Target{$Kind}{$Target}) {
17007 next;
17008 }
17009 $Kinds_Target{$Kind}{$Target} = 1;
17010
17011 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017012 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17013 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17014 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17015 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17016 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017017 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17018 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017020 $TYPE_PROBLEMS .= " </problem>\n";
17021 }
17022 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017023 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017025 $TYPE_PROBLEMS .= showVTables($TypeName);
17026 }
17027 $TYPE_PROBLEMS .= " </type>\n";
17028 }
17029 $TYPE_PROBLEMS .= " </header>\n";
17030 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017031 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 }
17033 else
17034 { # HTML
17035 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017036 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017037 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017038 my (%NameSpace_Type) = ();
17039 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017040 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017041 }
17042 foreach my $NameSpace (sort keys(%NameSpace_Type))
17043 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017044 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017045 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 +040017046 foreach my $TypeName (@SortedTypes)
17047 {
17048 my $ProblemNum = 1;
17049 my $TYPE_REPORT = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017050 my (%Kinds_Locations, %Kinds_Target) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017051
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017052 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges_Sev{$TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017053 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017054 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges_Sev{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017055 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017056 $Kinds_Locations{$Kind}{$Location} = 1;
17057
17058 my $Target = $TypeChanges_Sev{$TypeName}{$Kind}{$Location}{"Target"};
17059 if($Kinds_Target{$Kind}{$Target}) {
17060 next;
17061 }
17062 $Kinds_Target{$Kind}{$Target} = 1;
17063
17064 my %Problem = %{$TypeChanges_Sev{$TypeName}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17066 {
17067 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017068 $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 +040017069 $ProblemNum += 1;
17070 $ProblemsNum += 1;
17071 }
17072 }
17073 }
17074 $ProblemNum -= 1;
17075 if($TYPE_REPORT)
17076 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017077 my $Affected = getAffectedSymbols($Level, $TypeName, \%Kinds_Locations);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 my $ShowVTables = "";
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017079 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%Kinds_Locations)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017080 $ShowVTables = showVTables($TypeName);
17081 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017082
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017083 my $ShowType = show_Type($TypeName, 1, 1);
17084
17085 if($NameSpace)
17086 {
17087 $TYPE_REPORT = cut_Namespace($TYPE_REPORT, $NameSpace);
17088 $ShowType = cut_Namespace($ShowType, $NameSpace);
17089 $Affected = cut_Namespace($Affected, $NameSpace);
17090 $ShowVTables = cut_Namespace($ShowVTables, $NameSpace);
17091 }
17092
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017093 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='ext'>[+]</span> ".$ShowType;
17094 if($OldStyle) {
17095 $TYPE_PROBLEMS .= " ($ProblemNum)";
17096 }
17097 else {
17098 $TYPE_PROBLEMS .= " <span".getStyle("T", $TargetSeverity, $ProblemNum).">&nbsp;$ProblemNum&nbsp;</span>";
17099 }
17100 $TYPE_PROBLEMS .= $ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017101 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17102 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17103 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17104 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 }
17106 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017107 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108 }
17109 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017110
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 if($TYPE_PROBLEMS)
17112 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017113 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17114 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017115 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017116 { # Safe Changes
17117 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017118 }
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030017119 if($OldStyle) {
17120 $TYPE_PROBLEMS = "<h2>$Title ($ProblemsNum)</h2><hr/>\n".$TYPE_PROBLEMS;
17121 }
17122 else {
17123 $TYPE_PROBLEMS = "<h2>$Title <span".getStyle("T", $TargetSeverity, $ProblemsNum).">&nbsp;$ProblemsNum&nbsp;</span></h2><hr/>\n".$TYPE_PROBLEMS;
17124 }
17125 $TYPE_PROBLEMS = "<a name=\'".get_Anchor("Type", $Level, $TargetSeverity)."\'></a>\n".$TYPE_PROBLEMS.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 }
17127 }
17128 return $TYPE_PROBLEMS;
17129}
17130
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017131sub show_Type($$$)
17132{
17133 my ($Name, $Html, $LibVersion) = @_;
17134 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17135 $TType = lc($TType);
17136 if($TType=~/struct|union|enum/) {
17137 $Name=~s/\A\Q$TType\E //g;
17138 }
17139 if($Html) {
17140 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17141 }
17142 else {
17143 $Name = $TType." ".$Name;
17144 }
17145 return $Name;
17146}
17147
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017148sub get_Anchor($$$)
17149{
17150 my ($Kind, $Level, $Severity) = @_;
17151 if($JoinReport)
17152 {
17153 if($Severity eq "Safe") {
17154 return "Other_".$Level."_Changes_In_".$Kind."s";
17155 }
17156 else {
17157 return $Kind."_".$Level."_Problems_".$Severity;
17158 }
17159 }
17160 else
17161 {
17162 if($Severity eq "Safe") {
17163 return "Other_Changes_In_".$Kind."s";
17164 }
17165 else {
17166 return $Kind."_Problems_".$Severity;
17167 }
17168 }
17169}
17170
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017171sub showVTables($)
17172{
17173 my $TypeName = $_[0];
17174 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017175 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 if(defined $Type1{"VTable"}
17177 and keys(%{$Type1{"VTable"}}))
17178 {
17179 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017180 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017181 if(defined $Type2{"VTable"}
17182 and keys(%{$Type2{"VTable"}}))
17183 {
17184 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17185 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017186 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017188 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17189 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 }
17191 my $VTABLES = "";
17192 if($ReportFormat eq "xml")
17193 { # XML
17194 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017195 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017196 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017197 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017198 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17199 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017200 $VTABLES .= " </entry>\n";
17201 }
17202 $VTABLES .= " </vtable>\n\n";
17203 }
17204 else
17205 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017206 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017207 $VTABLES .= "<tr><th>Offset</th>";
17208 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017209 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017210 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 {
17212 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017213
17214 my $E1 = $Entries{$Index}{"E1"};
17215 my $E2 = $Entries{$Index}{"E2"};
17216
17217 if($E1 ne $E2
17218 and $E1!~/ 0x/
17219 and $E2!~/ 0x/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017221 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017223 $Color1 = " class='failed'";
17224 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017225 }
17226 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017227 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017228 }
17229 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017230 $VTABLES .= "<tr><th>".$Index."</th>\n";
17231 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17232 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017233 }
17234 $VTABLES .= "</table><br/>\n";
17235 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017236 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017237 }
17238 return $VTABLES;
17239 }
17240 }
17241 return "";
17242}
17243
17244sub simpleVEntry($)
17245{
17246 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017247 if(not defined $VEntry
17248 or $VEntry eq "") {
17249 return "";
17250 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017251
17252 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017253 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17254 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17255 if($VEntry=~/\A_ZThn.+\Z/) {
17256 $VEntry = "non-virtual thunk";
17257 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017258 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017259 # support for old GCC versions
17260 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17261 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17262 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17264 return $VEntry;
17265}
17266
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017267sub adjustParamPos($$$)
17268{
17269 my ($Pos, $Symbol, $LibVersion) = @_;
17270 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17271 {
17272 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17273 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17274 {
17275 return $Pos-1;
17276 }
17277
17278 return $Pos;
17279 }
17280
17281 return undef;
17282}
17283
17284sub getParamPos($$$)
17285{
17286 my ($Name, $Symbol, $LibVersion) = @_;
17287
17288 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17289 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17290 {
17291 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17292 foreach (keys(%{$Info->{"Param"}}))
17293 {
17294 if($Info->{"Param"}{$_}{"name"} eq $Name)
17295 {
17296 return $_;
17297 }
17298 }
17299 }
17300
17301 return undef;
17302}
17303
17304sub getParamName($)
17305{
17306 my $Loc = $_[0];
17307 $Loc=~s/\->.*//g;
17308 return $Loc;
17309}
17310
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017311sub getAffectedSymbols($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017312{
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017313 my ($Level, $Target_TypeName, $Kinds_Locations) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017314
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017315 my $LIMIT = 10;
17316 if(defined $AffectLimit) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017317 $LIMIT = $AffectLimit;
17318 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017319
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017320 my @Kinds = sort keys(%{$Kinds_Locations});
17321 my %KLocs = ();
17322 foreach my $Kind (@Kinds)
17323 {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030017324 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 +030017325 $KLocs{$Kind} = \@Locs;
17326 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017327
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017328 my %SymLocKind = ();
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017329 foreach my $Symbol (sort keys(%{$TypeProblemsIndex{$Level}{$Target_TypeName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017330 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017331 if(index($Symbol, "_Z")==0
17332 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017333 { # duplicated problems for C2 constructors, D2 and D0 destructors
17334 next;
17335 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017336
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017337 foreach my $Kind (@Kinds)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017339 foreach my $Loc (@{$KLocs{$Kind}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017340 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017341 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342 next;
17343 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017344
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017345 if(index($Symbol, "\@")!=-1
17346 or index($Symbol, "\$")!=-1)
17347 {
17348 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17349
17350 if($Level eq "Source")
17351 { # remove symbol version
17352 $Symbol = $SN;
17353 }
17354
17355 if($SV and defined $CompatProblems{$Level}{$SN}
17356 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
17357 { # duplicated problems for versioned symbols
17358 next;
17359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017361
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017362 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017363 if($Type_Name ne $Target_TypeName) {
17364 next;
17365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017366
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017367 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017368 last;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 }
17370 }
17371 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017372
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017373 %KLocs = (); # clear
17374
17375 my %SymSel = ();
17376 my $Num = 0;
17377 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymLocKind))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017378 {
17379 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17380 {
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017381 foreach my $Kind (sort keys(%{$SymLocKind{$Symbol}{$Loc}}))
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017382 {
17383 $SymSel{$Symbol}{"Loc"} = $Loc;
17384 $SymSel{$Symbol}{"Kind"} = $Kind;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017385 last LOOP;
17386 }
17387 }
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017388
17389 $Num += 1;
17390
17391 if($Num>=$LIMIT) {
17392 last;
17393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017394 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017395
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017398 if($ReportFormat eq "xml")
17399 { # XML
17400 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017401
17402 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017403 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017404 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017405 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017406 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017409 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017410 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017411 $Target .= " param=\"$PName\"";
17412 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017413 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017414 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017415 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017416 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017417 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017418 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017419 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017420
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017421 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017422 $Target .= " field=\"$1\"";
17423 }
17424
17425 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017426 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017427 $Affected .= " </symbol>\n";
17428 }
17429 $Affected .= " </affected>\n";
17430 }
17431 else
17432 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017433 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017434 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017435 my $Kind = $SymSel{$Symbol}{"Kind"};
17436 my $Loc = $SymSel{$Symbol}{"Loc"};
17437
17438 my $Desc = getAffectDesc($Level, $Symbol, $Kind, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017439 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017440 my $PName = getParamName($Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017441 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17442
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017443 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017444 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017445 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017446
Andrey Ponomarenkoba892272016-02-27 19:06:10 +030017447 if(keys(%SymLocKind)>$LIMIT) {
17448 $Affected .= " <b>...</b>\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017449 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017450
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017451 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017452 if($Affected)
17453 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017454 my $Num = keys(%SymLocKind);
17455 my $Per = show_number($Num*100/keys(%{$CheckedSymbols{$Level}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030017457 $Affected = $ContentSpanStart_Affected."[+] affected symbols: $Num ($Per\%)".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017458 }
17459 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017460
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461 return $Affected;
17462}
17463
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017464sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017466 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017467 if($L2=~/\A(retval|this)\b/
17468 and $L1!~/\A(retval|this)\b/)
17469 {
17470 if($L1!~/\-\>/) {
17471 return 1;
17472 }
17473 elsif($L2=~/\-\>/) {
17474 return 1;
17475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017476 }
17477 return 0;
17478}
17479
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017480sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017481{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017482 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017483
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017484 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017485
17486 my $Location_I = $Location;
17487 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17488
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017489 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017490
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017491 if($Kind eq "Overridden_Virtual_Method"
17492 or $Kind eq "Overridden_Virtual_Method_B") {
17493 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17494 }
17495 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17496 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017497 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017499 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17500 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017501 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17502 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17503
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 if($ClassName eq $Problem{"Type_Name"}) {
17505 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17506 }
17507 else {
17508 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17509 }
17510 }
17511 else
17512 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017513 my $TypeID = undef;
17514
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017515 if($Location=~/retval/)
17516 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017517 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017518 push(@Sentence, "Field \'".$Location."\' in return value");
17519 }
17520 else {
17521 push(@Sentence, "Return value");
17522 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017523
17524 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017525 }
17526 elsif($Location=~/this/)
17527 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017528 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017529 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17530 }
17531 else {
17532 push(@Sentence, "\'this\' pointer");
17533 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017534
17535 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017536 }
17537 else
17538 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017539
17540 my $PName = getParamName($Location);
17541 my $PPos = getParamPos($PName, $Symbol, 1);
17542
17543 if(index($Location, "->")!=-1) {
17544 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017545 }
17546 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017547 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017548 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017549 if($PName) {
17550 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017551 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017552
17553 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17554 }
17555
17556 if($Location!~/this/)
17557 {
17558 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017559 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017560 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017561 push(@Sentence, "(pointer)");
17562 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017563 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017564 push(@Sentence, "(reference)");
17565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017566 }
17567 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017568
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017569 if($Location eq "this") {
17570 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17571 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017572 else
17573 {
17574 my $Location_T = $Location;
17575 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17576
17577 my $TypeID_Problem = $TypeID;
17578 if($Location_T) {
17579 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17580 }
17581
17582 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17583 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17584 }
17585 else {
17586 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017588 }
17589 }
17590 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017591 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017592 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 +040017593 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017594
17595 my $Sent = join(" ", @Sentence);
17596
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017597 $Sent=~s/->/./g;
17598
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017599 if($ReportFormat eq "xml")
17600 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017601 $Sent=~s/'//g;
17602 }
17603
17604 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017605}
17606
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017607sub getFieldType($$$)
17608{
17609 my ($Location, $TypeId, $LibVersion) = @_;
17610
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017611 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017612
17613 foreach my $Name (@Fields)
17614 {
17615 my %Info = get_BaseType($TypeId, $LibVersion);
17616
17617 foreach my $Pos (keys(%{$Info{"Memb"}}))
17618 {
17619 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17620 {
17621 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17622 last;
17623 }
17624 }
17625 }
17626
17627 return $TypeId;
17628}
17629
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017630sub get_XmlSign($$)
17631{
17632 my ($Symbol, $LibVersion) = @_;
17633 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17634 my $Report = "";
17635 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17636 {
17637 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017638 my $Type = $Info->{"Param"}{$Pos}{"type"};
17639 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017640 foreach my $Typedef (keys(%ChangedTypedef))
17641 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017642 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17643 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017645 }
17646 $Report .= " <param pos=\"$Pos\">\n";
17647 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017648 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017649 $Report .= " </param>\n";
17650 }
17651 if(my $Return = $Info->{"Return"})
17652 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017653 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017654 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017655 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 $Report .= " </retval>\n";
17657 }
17658 return $Report;
17659}
17660
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017661sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017662{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017663 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017664 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017665 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017666 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017667 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17668 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017669 next;
17670 }
17671 $Report .= " <symbol name=\"$Symbol\">\n";
17672 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017673 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017674 {
17675 if(defined $CompleteSignature{1}{$Symbol}
17676 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17677 {
17678 $P1 = get_XmlSign($Symbol, 1);
17679 $S1 = get_Signature($Symbol, 1);
17680 }
17681 elsif($Symbol=~/\A(_Z|\?)/) {
17682 $S1 = $tr_name{$Symbol};
17683 }
17684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017685 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017686 {
17687 if(defined $CompleteSignature{2}{$Symbol}
17688 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17689 {
17690 $P2 = get_XmlSign($Symbol, 2);
17691 $S2 = get_Signature($Symbol, 2);
17692 }
17693 elsif($Symbol=~/\A(_Z|\?)/) {
17694 $S2 = $tr_name{$Symbol};
17695 }
17696 }
17697 if($S1)
17698 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017699 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017700 $Report .= $P1;
17701 $Report .= " </old>\n";
17702 }
17703 if($S2 and $S2 ne $S1)
17704 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017705 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017706 $Report .= $P2;
17707 $Report .= " </new>\n";
17708 }
17709 $Report .= " </symbol>\n";
17710 }
17711 $Report .= "</symbols_info>\n";
17712 return $Report;
17713}
17714
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017715sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017716{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017717 my ($Level, $Report) = @_;
17718 if($ReportFormat eq "xml") {
17719 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017720 }
17721 if($StdOut)
17722 { # --stdout option
17723 print STDOUT $Report;
17724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017725 else
17726 {
17727 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017728 mkpath(get_dirname($RPath));
17729
17730 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17731 print REPORT $Report;
17732 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017733 }
17734}
17735
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017736sub getReport($)
17737{
17738 my $Level = $_[0];
17739 if($ReportFormat eq "xml")
17740 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017741 if($Level eq "Join")
17742 {
17743 my $Report = "<reports>\n";
17744 $Report .= getReport("Binary");
17745 $Report .= getReport("Source");
17746 $Report .= "</reports>\n";
17747 return $Report;
17748 }
17749 else
17750 {
17751 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17752 my ($Summary, $MetaData) = get_Summary($Level);
17753 $Report .= $Summary."\n";
17754 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17755 $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 +040017756
17757 # additional symbols info (if needed)
17758 # $Report .= get_Report_SymbolsInfo($Level);
17759
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017760 $Report .= "</report>\n";
17761 return $Report;
17762 }
17763 }
17764 else
17765 { # HTML
17766 my $CssStyles = readModule("Styles", "Report.css");
17767 my $JScripts = readModule("Scripts", "Sections.js");
17768 if($Level eq "Join")
17769 {
17770 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17771 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017772 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017773 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17774 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 +040017775 my ($BSummary, $BMetaData) = get_Summary("Binary");
17776 my ($SSummary, $SMetaData) = get_Summary("Source");
17777 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 +030017778 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017779 <br/>
17780 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017781 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17782 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017783 </div>";
17784 $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>";
17785 $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 +030017786 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017787 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017788 return $Report;
17789 }
17790 else
17791 {
17792 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017793 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17794 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17795 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 +040017796 if($Level eq "Binary")
17797 {
17798 if(getArch(1) eq getArch(2)
17799 and getArch(1) ne "unknown") {
17800 $Description .= " on ".showArch(getArch(1));
17801 }
17802 }
17803 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 +030017804 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017805 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17806 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17807 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017808 $Report .= "</div>\n<br/><br/><br/>\n";
17809 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017810 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017811 return $Report;
17812 }
17813 }
17814}
17815
17816sub createReport()
17817{
17818 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017819 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017820 writeReport("Join", getReport("Join"));
17821 }
17822 elsif($DoubleReport)
17823 { # default
17824 writeReport("Binary", getReport("Binary"));
17825 writeReport("Source", getReport("Source"));
17826 }
17827 elsif($BinaryOnly)
17828 { # --binary
17829 writeReport("Binary", getReport("Binary"));
17830 }
17831 elsif($SourceOnly)
17832 { # --source
17833 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017834 }
17835}
17836
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017837sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017838{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017839 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017840
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030017841 $Footer .= "<hr/>\n";
17842 $Footer .= "<div class='footer' align='right'>";
17843 $Footer .= "<i>Generated by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;</i>\n";
17844 $Footer .= "</div>\n";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017845 $Footer .= "<br/>\n";
17846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017847 return $Footer;
17848}
17849
17850sub get_Report_Problems($$)
17851{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017852 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017853
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017854 my $Report = get_Report_TypeProblems($Severity, $Level);
17855 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017856 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017857 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017858
17859 if($Severity eq "Low" or $Severity eq "Safe") {
17860 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017861 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017863 if($ReportFormat eq "html")
17864 {
17865 if($Report)
17866 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017867 if($JoinReport)
17868 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017869 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017870 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17871 }
17872 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017873 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017875 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017876 else
17877 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017878 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017879 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17880 }
17881 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017882 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017884 }
17885 }
17886 }
17887 return $Report;
17888}
17889
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017890sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017891{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017892 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
Andrey Ponomarenko3ad495d2016-04-18 21:15:53 +030017893
17894 my $Head = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
17895 $Head .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n";
17896 $Head .= "<head>\n";
17897 $Head .= "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
17898 $Head .= "<meta name=\"keywords\" content=\"$Keywords\" />\n";
17899 $Head .= "<meta name=\"description\" content=\"$Description\" />\n";
17900 $Head .= "<title>$Title</title>\n";
17901 $Head .= "<style type=\"text/css\">\n$Styles</style>\n";
17902 $Head .= "<script type=\"text/javascript\" language=\"JavaScript\">\n<!--\n$Scripts\n-->\n</script>\n";
17903 $Head .= "</head>\n";
17904
17905 return $Head;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017906}
17907
17908sub insertIDs($)
17909{
17910 my $Text = $_[0];
17911 while($Text=~/CONTENT_ID/)
17912 {
17913 if(int($Content_Counter)%2) {
17914 $ContentID -= 1;
17915 }
17916 $Text=~s/CONTENT_ID/c_$ContentID/;
17917 $ContentID += 1;
17918 $Content_Counter += 1;
17919 }
17920 return $Text;
17921}
17922
17923sub checkPreprocessedUnit($)
17924{
17925 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017926 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017927 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017928 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017929
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017930 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017931 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017932 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017933 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017934 chomp($Line);
17935 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017936 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017937 $CurHeader = path_format($1, $OSgroup);
17938 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017939 $CurClass = "";
17940
17941 if(index($CurHeader, $TMP_DIR)==0) {
17942 next;
17943 }
17944
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017945 if(substr($CurHeaderName, 0, 1) eq "<")
17946 { # <built-in>, <command-line>, etc.
17947 $CurHeaderName = "";
17948 $CurHeader = "";
17949 }
17950
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017951 if($ExtraInfo)
17952 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017953 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017954 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17955 }
17956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017957 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017958 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017959 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017960 if($CurHeaderName)
17961 {
17962 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17963 and not $Registered_Headers{$Version}{$CurHeader})
17964 { # not a target
17965 next;
17966 }
17967 if(not is_target_header($CurHeaderName, 1)
17968 and not is_target_header($CurHeaderName, 2))
17969 { # user-defined header
17970 next;
17971 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017972 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017973 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017974
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017975 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017976 {
17977 my ($Name, $Value) = ($1, $2);
17978 if(not $Constants{$Version}{$Name}{"Access"})
17979 {
17980 $Constants{$Version}{$Name}{"Access"} = "public";
17981 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017982 if($CurHeaderName) {
17983 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17984 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017985 }
17986 }
17987 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17988 $Constants{$Version}{$1}{"Access"} = "private";
17989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017990 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017991 else
17992 {
17993 if(defined $ExtraDump)
17994 {
17995 if($Line=~/(\w+)\s*\(/)
17996 { # functions
17997 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17998 }
17999 #elsif($Line=~/(\w+)\s*;/)
18000 #{ # data
18001 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18002 #}
18003 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18004 $CurClass = $2;
18005 }
18006 }
18007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018008 }
18009 close(PREPROC);
18010 foreach my $Constant (keys(%{$Constants{$Version}}))
18011 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018012 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18013 {
18014 delete($Constants{$Version}{$Constant});
18015 next;
18016 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018017 if(not $ExtraDump and ($Constant=~/_h\Z/i
18018 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018019 { # skip
18020 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018021 }
18022 else {
18023 delete($Constants{$Version}{$Constant}{"Access"});
18024 }
18025 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018026 if($Debug)
18027 {
18028 mkpath($DEBUG_PATH{$Version});
18029 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018031}
18032
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018033sub uncoverConstant($$)
18034{
18035 my ($LibVersion, $Constant) = @_;
18036 return "" if(not $LibVersion or not $Constant);
18037 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18038 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18039 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18040 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018041
18042 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018043 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018044 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18045 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018046 {
18047 push(@RecurConstant, $Constant);
18048 my $Uncovered = uncoverConstant($LibVersion, $Value);
18049 if($Uncovered ne "") {
18050 $Value = $Uncovered;
18051 }
18052 pop(@RecurConstant);
18053 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018054
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018055 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018056 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018057 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18058 }
18059 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18060}
18061
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018062sub simpleConstant($$)
18063{
18064 my ($LibVersion, $Value) = @_;
18065 if($Value=~/\W/)
18066 {
18067 my $Value_Copy = $Value;
18068 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18069 {
18070 my $Word = $1;
18071 if($Value!~/$Word\s*\(/)
18072 {
18073 my $Val = uncoverConstant($LibVersion, $Word);
18074 if($Val ne "")
18075 {
18076 $Value=~s/\b$Word\b/$Val/g;
18077 }
18078 }
18079 }
18080 }
18081 return $Value;
18082}
18083
18084sub computeValue($)
18085{
18086 my $Value = $_[0];
18087
18088 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18089 return $1;
18090 }
18091
18092 if($Value=~/\A[\d\-\+()]+\Z/) {
18093 return eval($Value);
18094 }
18095
18096 return $Value;
18097}
18098
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018099my %IgnoreConstant = map {$_=>1} (
18100 "VERSION",
18101 "VERSIONCODE",
18102 "VERNUM",
18103 "VERS_INFO",
18104 "PATCHLEVEL",
18105 "INSTALLPREFIX",
18106 "VBUILD",
18107 "VPATCH",
18108 "VMINOR",
18109 "BUILD_STRING",
18110 "BUILD_TIME",
18111 "PACKAGE_STRING",
18112 "PRODUCTION",
18113 "CONFIGURE_COMMAND",
18114 "INSTALLDIR",
18115 "BINDIR",
18116 "CONFIG_FILE_PATH",
18117 "DATADIR",
18118 "EXTENSION_DIR",
18119 "INCLUDE_PATH",
18120 "LIBDIR",
18121 "LOCALSTATEDIR",
18122 "SBINDIR",
18123 "SYSCONFDIR",
18124 "RELEASE",
18125 "SOURCE_ID",
18126 "SUBMINOR",
18127 "MINOR",
18128 "MINNOR",
18129 "MINORVERSION",
18130 "MAJOR",
18131 "MAJORVERSION",
18132 "MICRO",
18133 "MICROVERSION",
18134 "BINARY_AGE",
18135 "INTERFACE_AGE",
18136 "CORE_ABI",
18137 "PATCH",
18138 "COPYRIGHT",
18139 "TIMESTAMP",
18140 "REVISION",
18141 "PACKAGE_TAG",
18142 "PACKAGEDATE",
18143 "NUMVERSION",
18144 "Release",
18145 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018146);
18147
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018148sub constantFilter($$$)
18149{
18150 my ($Name, $Value, $Level) = @_;
18151
18152 if($Level eq "Binary")
18153 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018154 if($Name=~/_t\Z/)
18155 { # __malloc_ptr_t
18156 return 1;
18157 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018158 foreach (keys(%IgnoreConstant))
18159 {
18160 if($Name=~/(\A|_)$_(_|\Z)/)
18161 { # version
18162 return 1;
18163 }
18164 if(/\A[A-Z].*[a-z]\Z/)
18165 {
18166 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18167 { # version
18168 return 1;
18169 }
18170 }
18171 }
18172 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18173 { # version
18174 return 1;
18175 }
18176 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18177 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18178 return 1;
18179 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018180
18181 if($Value=~/\A["'].*['"]/i)
18182 { # string
18183 return 0;
18184 }
18185
18186 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18187 { # static int gcry_pth_init
18188 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018189 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018190 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018191 return 1;
18192 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018193 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018194 { # foo(p)
18195 return 1;
18196 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018197 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018198 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018199 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018200 return 1;
18201 }
18202 }
18203
18204 return 0;
18205}
18206
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018207sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018208{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018209 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018210 foreach my $Constant (keys(%{$Constants{1}}))
18211 {
18212 if($SkipConstants{1}{$Constant})
18213 { # skipped by the user
18214 next;
18215 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018216
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018217 if(my $Header = $Constants{1}{$Constant}{"Header"})
18218 {
18219 if(not is_target_header($Header, 1)
18220 and not is_target_header($Header, 2))
18221 { # user-defined header
18222 next;
18223 }
18224 }
18225 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018226 next;
18227 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018228
18229 my $Old_Value = uncoverConstant(1, $Constant);
18230
18231 if(constantFilter($Constant, $Old_Value, $Level))
18232 { # separate binary and source problems
18233 next;
18234 }
18235
18236 if(not defined $Constants{2}{$Constant}{"Value"})
18237 { # removed
18238 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18239 "Target"=>$Constant,
18240 "Old_Value"=>$Old_Value );
18241 next;
18242 }
18243
18244 if($Constants{2}{$Constant}{"Value"} eq "")
18245 { # empty value
18246 # TODO: implement a rule
18247 next;
18248 }
18249
18250 my $New_Value = uncoverConstant(2, $Constant);
18251
18252 my $Old_Value_Pure = $Old_Value;
18253 my $New_Value_Pure = $New_Value;
18254
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018255 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18256 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18257 $New_Value_Pure=~s/(\W)\s+/$1/g;
18258 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018259
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018260 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018261
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018262 if($New_Value_Pure ne $Old_Value_Pure)
18263 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018264 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18265 { # complex values
18266 next;
18267 }
18268 if(computeValue($Old_Value) eq computeValue($New_Value))
18269 { # expressions
18270 next;
18271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018272 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18273 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18274 next;
18275 }
18276 if($Old_Value eq "0" and $New_Value eq "NULL")
18277 { # 0 => NULL
18278 next;
18279 }
18280 if($Old_Value eq "NULL" and $New_Value eq "0")
18281 { # NULL => 0
18282 next;
18283 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018284 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018285 "Target"=>$Constant,
18286 "Old_Value"=>$Old_Value,
18287 "New_Value"=>$New_Value );
18288 }
18289 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018290
18291 foreach my $Constant (keys(%{$Constants{2}}))
18292 {
18293 if(not defined $Constants{1}{$Constant}{"Value"})
18294 {
18295 if($SkipConstants{2}{$Constant})
18296 { # skipped by the user
18297 next;
18298 }
18299
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018300 if(my $Header = $Constants{2}{$Constant}{"Header"})
18301 {
18302 if(not is_target_header($Header, 1)
18303 and not is_target_header($Header, 2))
18304 { # user-defined header
18305 next;
18306 }
18307 }
18308 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018309 next;
18310 }
18311
18312 my $New_Value = uncoverConstant(2, $Constant);
18313 if(not defined $New_Value or $New_Value eq "") {
18314 next;
18315 }
18316
18317 if(constantFilter($Constant, $New_Value, $Level))
18318 { # separate binary and source problems
18319 next;
18320 }
18321
18322 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18323 "Target"=>$Constant,
18324 "New_Value"=>$New_Value );
18325 }
18326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018327}
18328
18329sub convert_integer($)
18330{
18331 my $Value = $_[0];
18332 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018333 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018334 return hex($Value);
18335 }
18336 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018337 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018338 return oct($Value);
18339 }
18340 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018341 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018342 return oct($Value);
18343 }
18344 else {
18345 return $Value;
18346 }
18347}
18348
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018349sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018350{
18351 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018352 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018353 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018354 {
18355 if($LibVersion==1)
18356 {
18357 printMsg("WARNING", "checking headers only");
18358 $CheckHeadersOnly = 1;
18359 }
18360 else {
18361 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18362 }
18363 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018364
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018365 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018366 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018367 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018368
18369 if($CheckUndefined)
18370 {
18371 my %UndefinedLibs = ();
18372
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018373 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18374
18375 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018376 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018377 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018378 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018379 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018380 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018381 if($Symbol_Library{$LibVersion}{$Symbol}
18382 or $DepSymbol_Library{$LibVersion}{$Symbol})
18383 { # exported by target library
18384 next;
18385 }
18386 if(index($Symbol, '@')!=-1)
18387 { # exported default symbol version (@@)
18388 $Symbol=~s/\@/\@\@/;
18389 if($Symbol_Library{$LibVersion}{$Symbol}
18390 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18391 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018392 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018393 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018394 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18395 $UndefinedLibs{$Path} = 1;
18396 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018397 }
18398 }
18399 }
18400 if($ExtraInfo)
18401 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018402 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018403 {
18404 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018405 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018406 foreach (@Paths)
18407 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018408 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018409 my ($Dir, $Name) = separate_path($_);
18410
18411 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018412 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018413 }
18414
18415 $Name = parse_libname($Name, "name", $OStarget);
18416 $Name=~s/\Alib//;
18417
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018418 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018419 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018420
18421 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18422 {
18423 $LibString = " -L".esc($Dir).$LibString;
18424 }
18425
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018426 writeFile($ExtraInfo."/libs-string", $LibString);
18427 }
18428 }
18429 }
18430
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018431 if($ExtraInfo) {
18432 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18433 }
18434
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018435 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018436 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018437 if($#LibPaths!=-1)
18438 {
18439 if(not keys(%{$Symbol_Library{$LibVersion}}))
18440 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018441 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018442 printMsg("WARNING", "checking headers only");
18443 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018444 }
18445 }
18446 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018447
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018448 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018449 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018450}
18451
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018452my %Prefix_Lib_Map=(
18453 # symbols for autodetecting library dependencies (by prefix)
18454 "pthread_" => ["libpthread"],
18455 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18456 "cairo_" => ["libcairo"],
18457 "gtk_" => ["libgtk-x11-2.0"],
18458 "atk_" => ["libatk-1.0"],
18459 "gdk_" => ["libgdk-x11-2.0"],
18460 "gl" => ["libGL"],
18461 "glu" => ["libGLU"],
18462 "popt" => ["libpopt"],
18463 "Py" => ["libpython"],
18464 "jpeg_" => ["libjpeg"],
18465 "BZ2_" => ["libbz2"],
18466 "Fc" => ["libfontconfig"],
18467 "Xft" => ["libXft"],
18468 "SSL_" => ["libssl"],
18469 "sem_" => ["libpthread"],
18470 "snd_" => ["libasound"],
18471 "art_" => ["libart_lgpl_2"],
18472 "dbus_g" => ["libdbus-glib-1"],
18473 "GOMP_" => ["libgomp"],
18474 "omp_" => ["libgomp"],
18475 "cms" => ["liblcms"]
18476);
18477
18478my %Pattern_Lib_Map=(
18479 "SL[a-z]" => ["libslang"]
18480);
18481
18482my %Symbol_Lib_Map=(
18483 # symbols for autodetecting library dependencies (by name)
18484 "pow" => "libm",
18485 "fmod" => "libm",
18486 "sin" => "libm",
18487 "floor" => "libm",
18488 "cos" => "libm",
18489 "dlopen" => "libdl",
18490 "deflate" => "libz",
18491 "inflate" => "libz",
18492 "move_panel" => "libpanel",
18493 "XOpenDisplay" => "libX11",
18494 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018495 "clock_gettime" => "librt",
18496 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018497);
18498
18499sub find_SymbolLibs($$)
18500{
18501 my ($LibVersion, $Symbol) = @_;
18502
18503 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18504 { # debug symbols
18505 return ();
18506 }
18507
18508 my %Paths = ();
18509
18510 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18511 {
18512 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18513 $Paths{$Path} = 1;
18514 }
18515 }
18516
18517 if(my $SymbolPrefix = getPrefix($Symbol))
18518 {
18519 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18520 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18521 }
18522
18523 if(not keys(%Paths))
18524 {
18525 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18526 {
18527 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18528 {
18529 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18530 $Paths{$Path} = 1;
18531 }
18532 }
18533 }
18534 }
18535
18536 if(not keys(%Paths))
18537 {
18538 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18539 {
18540 if($Symbol=~/\A$Prefix/)
18541 {
18542 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18543 {
18544 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18545 $Paths{$Path} = 1;
18546 }
18547 }
18548 }
18549 }
18550 }
18551
18552 if(not keys(%Paths))
18553 {
18554 if($SymbolPrefix)
18555 { # try to find a library by symbol prefix
18556 if($SymbolPrefix eq "inotify" and
18557 index($Symbol, "\@GLIBC")!=-1)
18558 {
18559 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18560 $Paths{$Path} = 1;
18561 }
18562 }
18563 else
18564 {
18565 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18566 $Paths{$Path} = 1;
18567 }
18568 }
18569 }
18570 }
18571
18572 if(my @Paths = keys(%Paths)) {
18573 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18574 }
18575 }
18576 return keys(%Paths);
18577}
18578
18579sub get_LibPath_Prefix($$)
18580{
18581 my ($LibVersion, $Prefix) = @_;
18582
18583 $Prefix = lc($Prefix);
18584 $Prefix=~s/[_]+\Z//g;
18585
18586 foreach ("-2", "2", "-1", "1", "")
18587 { # libgnome-2.so
18588 # libxml2.so
18589 # libdbus-1.so
18590 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18591 return $Path;
18592 }
18593 }
18594 return "";
18595}
18596
18597sub getPrefix($)
18598{
18599 my $Str = $_[0];
18600 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18601 { # XmuValidArea: Xmu
18602 return $1;
18603 }
18604 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18605 { # snfReadFont: snf
18606 return $1;
18607 }
18608 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18609 { # XRRTimes: XRR
18610 return $1;
18611 }
18612 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18613 { # H5HF_delete: H5
18614 return $1;
18615 }
18616 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18617 { # alarm_event_add: alarm_
18618 return $1;
18619 }
18620 elsif($Str=~/\A(([a-z])\2{1,})/i)
18621 { # ffopen
18622 return $1;
18623 }
18624 return "";
18625}
18626
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018627sub getSymbolSize($$)
18628{ # size from the shared library
18629 my ($Symbol, $LibVersion) = @_;
18630 return 0 if(not $Symbol);
18631 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18632 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18633 {
18634 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18635 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18636 {
18637 if($Size<0) {
18638 return -$Size;
18639 }
18640 }
18641 }
18642 return 0;
18643}
18644
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018645sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018646{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18647 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018648 my ($Name, $Type) = @_;
18649
18650 # single
18651 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018652 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018653 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018654 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018655 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018656
18657 # double
18658 if($Name=~/$DEFAULT_STD_PARMS/)
18659 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018660 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018661 {
18662 my ($ShortName, $FuncParams) = split_Signature($Name);
18663
18664 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18665 {
18666 if(index($FParam, "<")!=-1)
18667 {
18668 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18669 my $FParam_N = canonifyName($FParam, "T");
18670 if($FParam_N ne $FParam) {
18671 $Name=~s/\Q$FParam\E/$FParam_N/g;
18672 }
18673 }
18674 }
18675 }
18676 elsif($Type eq "T")
18677 {
18678 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18679
18680 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018681 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018682 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018683 my $FParam = $TParams[0];
18684 foreach my $Pos (1 .. $#TParams)
18685 {
18686 my $TParam = $TParams[$Pos];
18687 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18688 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18689 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018690 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018691 }
18692 }
18693 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018694 if($Type eq "S") {
18695 return formatName($Name, "S");
18696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018697 return $Name;
18698}
18699
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018700sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018701{
18702 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018703 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018704 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018705 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018706 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018707 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018708 next if($tr_name{$Symbol});
18709 $Symbol=~s/[\@\$]+(.*)\Z//;
18710 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018711 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018712 elsif(index($Symbol, "?")==0)
18713 {
18714 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018715 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018716 }
18717 else
18718 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018719 $tr_name{$Symbol} = $Symbol;
18720 $mangled_name_gcc{$Symbol} = $Symbol;
18721 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018722 }
18723 }
18724 if($#MnglNames1 > -1)
18725 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018726 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018727 foreach my $MnglName (@MnglNames1)
18728 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018729 if(my $Unmangled = pop(@UnmangledNames))
18730 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018731 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018732 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18733 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18734 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018735 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018736 and $tr_name{$MnglName}=~/vtable for (.+)/)
18737 { # bind class name and v-table symbol
18738 my $ClassName = $1;
18739 $ClassVTable{$ClassName} = $MnglName;
18740 $VTableClass{$MnglName} = $ClassName;
18741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018742 }
18743 }
18744 }
18745 if($#MnglNames2 > -1)
18746 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018747 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018748 foreach my $MnglName (@MnglNames2)
18749 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018750 if(my $Unmangled = pop(@UnmangledNames))
18751 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018752 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018753 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018755 }
18756 }
18757 return \%tr_name;
18758}
18759
18760sub link_symbol($$$)
18761{
18762 my ($Symbol, $RunWith, $Deps) = @_;
18763 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18764 return 1;
18765 }
18766 if($Deps eq "+Deps")
18767 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018768 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018769 return 1;
18770 }
18771 }
18772 return 0;
18773}
18774
18775sub link_symbol_internal($$$)
18776{
18777 my ($Symbol, $RunWith, $Where) = @_;
18778 return 0 if(not $Where or not $Symbol);
18779 if($Where->{$RunWith}{$Symbol})
18780 { # the exact match by symbol name
18781 return 1;
18782 }
18783 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18784 { # indirect symbol version, i.e.
18785 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018786 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018787 if($Where->{$RunWith}{$VSym}) {
18788 return 1;
18789 }
18790 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018791 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018792 if($Sym and $Ver)
18793 { # search for the symbol with the same version
18794 # or without version
18795 if($Where->{$RunWith}{$Sym})
18796 { # old: foo@v|foo@@v
18797 # new: foo
18798 return 1;
18799 }
18800 if($Where->{$RunWith}{$Sym."\@".$Ver})
18801 { # old: foo|foo@@v
18802 # new: foo@v
18803 return 1;
18804 }
18805 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18806 { # old: foo|foo@v
18807 # new: foo@@v
18808 return 1;
18809 }
18810 }
18811 return 0;
18812}
18813
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018814sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018815{
18816 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018817 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018818 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018819 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018820 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018821 my $NM = get_CmdPath("nm");
18822 if(not $NM) {
18823 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018824 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018825 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018826 while(<APP>)
18827 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018828 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 push(@Imported, $1);
18830 }
18831 }
18832 close(APP);
18833 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018834 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018835 {
18836 my $DumpBinCmd = get_CmdPath("dumpbin");
18837 if(not $DumpBinCmd) {
18838 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18839 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018840 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018841 while(<APP>)
18842 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018843 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18844 push(@Imported, $1);
18845 }
18846 }
18847 close(APP);
18848 }
18849 else
18850 {
18851 my $ReadelfCmd = get_CmdPath("readelf");
18852 if(not $ReadelfCmd) {
18853 exitStatus("Not_Found", "can't find \"readelf\"");
18854 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018855 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018856 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018857 while(<APP>)
18858 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018859 if(defined $symtab)
18860 { # do nothing with symtab
18861 if(index($_, "'.dynsym'")!=-1)
18862 { # dynamic table
18863 $symtab = undef;
18864 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018865 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018866 elsif(index($_, "'.symtab'")!=-1)
18867 { # symbol table
18868 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018869 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018870 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018871 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018872 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18873 if($Ndx eq "UND")
18874 { # only imported symbols
18875 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 }
18877 }
18878 }
18879 close(APP);
18880 }
18881 return @Imported;
18882}
18883
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018884my %ELF_BIND = map {$_=>1} (
18885 "WEAK",
18886 "GLOBAL"
18887);
18888
18889my %ELF_TYPE = map {$_=>1} (
18890 "FUNC",
18891 "IFUNC",
18892 "OBJECT",
18893 "COMMON"
18894);
18895
18896my %ELF_VIS = map {$_=>1} (
18897 "DEFAULT",
18898 "PROTECTED"
18899);
18900
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018901sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018902{ # read the line of 'readelf' output corresponding to the symbol
18903 my @Info = split(/\s+/, $_[0]);
18904 # Num: Value Size Type Bind Vis Ndx Name
18905 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018906 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018907 shift(@Info); # spaces
18908 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018909
18910 if($#Info==7)
18911 { # UND SYMBOL (N)
18912 if($Info[7]=~/\(\d+\)/) {
18913 pop(@Info);
18914 }
18915 }
18916
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018917 if($#Info!=6)
18918 { # other lines
18919 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018920 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018921 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 return () if(not defined $ELF_BIND{$Info[3]});
18923 return () if(not defined $ELF_VIS{$Info[4]});
18924 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18925 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18926 return ();
18927 }
18928 if($OStarget eq "symbian")
18929 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18930 if(index($Info[6], "_._.absent_export_")!=-1)
18931 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18932 return ();
18933 }
18934 $Info[6]=~s/\@.+//g; # remove version
18935 }
18936 if(index($Info[2], "0x") == 0)
18937 { # size == 0x3d158
18938 $Info[2] = hex($Info[2]);
18939 }
18940 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941}
18942
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018943sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018944{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018945 my ($LibVersion, $Name) = @_;
18946 return "" if(not $LibVersion or not $Name);
18947 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18948 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018949 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018950 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18951}
18952
18953sub get_LibPath_I($$)
18954{
18955 my ($LibVersion, $Name) = @_;
18956 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018957 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958 if(-f $Name)
18959 { # absolute path
18960 return $Name;
18961 }
18962 else
18963 { # broken
18964 return "";
18965 }
18966 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018967 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018968 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018969 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018970 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018971 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018972 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018973 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018974 }
18975 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18976 { # ldconfig default paths
18977 return $DefaultPath;
18978 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018979 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018980 { # search in default linker directories
18981 # and then in all system paths
18982 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018983 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 }
18985 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018986 if(not defined $Cache{"checkSystemFiles"}) {
18987 checkSystemFiles();
18988 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018989 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18990 return $AllObjects[0];
18991 }
18992 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18993 {
18994 if($ShortName ne $Name)
18995 { # FIXME: check this case
18996 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18997 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018998 }
18999 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019000 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 # can't find
19002 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019003}
19004
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019005sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019006{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019007 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19008 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019009
19010 my $Real_Path = realpath($Lib_Path);
19011
19012 if(not $Real_Path)
19013 { # broken link
19014 return ();
19015 }
19016
19017 my $Lib_Name = get_filename($Real_Path);
19018
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019019 if($ExtraInfo)
19020 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019021 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019022 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019023 }
19024
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019025 if($IsNeededLib)
19026 {
19027 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19028 return ();
19029 }
19030 }
19031 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019032 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019033
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019034 push(@RecurLib, $Lib_Name);
19035 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019036 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19037
19038 if(not $IsNeededLib)
19039 { # special cases: libstdc++ and libc
19040 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19041 {
19042 if($ShortName eq "libstdc++")
19043 { # libstdc++.so.6
19044 $STDCXX_TESTING = 1;
19045 }
19046 elsif($ShortName eq "libc")
19047 { # libc-2.11.3.so
19048 $GLIBC_TESTING = 1;
19049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019050 }
19051 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019052 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019053 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019054 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019055 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019056 mkpath(get_dirname($DebugPath));
19057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019058 if($OStarget eq "macos")
19059 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019060 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019061 if(not $NM) {
19062 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019063 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019064 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019065 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019066 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019067 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019068 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019069 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019070 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019071 else
19072 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019073 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019074 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019075 while(<LIB>)
19076 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019077 if($CheckUndefined)
19078 {
19079 if(not $IsNeededLib)
19080 {
19081 if(/ U _([\w\$]+)\s*\Z/)
19082 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019083 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019084 next;
19085 }
19086 }
19087 }
19088
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019089 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019090 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019091 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019092 if($IsNeededLib)
19093 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019094 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019095 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019096 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19097 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019100 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019101 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019102 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19103 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019104 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19105 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019106 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019107 setLanguage($LibVersion, "C++");
19108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019110 }
19111 }
19112 }
19113 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019114
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019115 if($Deps)
19116 {
19117 if($LIB_TYPE eq "dynamic")
19118 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019119
19120 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019121 if(not $OtoolCmd) {
19122 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019123 }
19124
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019125 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19126 while(<LIB>)
19127 {
19128 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19129 and $1 ne $Lib_Path) {
19130 $NeededLib{$1} = 1;
19131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019132 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019133 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019135 }
19136 }
19137 elsif($OStarget eq "windows")
19138 { # Windows *.dll, *.lib
19139 my $DumpBinCmd = get_CmdPath("dumpbin");
19140 if(not $DumpBinCmd) {
19141 exitStatus("Not_Found", "can't find \"dumpbin\"");
19142 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019143 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019144 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019145 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019146 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019147 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019148 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019149 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019150 else
19151 { # write to pipe
19152 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019154 while(<LIB>)
19155 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19156 # 1198 4AD SetThreadToken (forwarded to ...)
19157 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019158 # 1 0 00005B30 ??0?N = ... (with pdb)
19159 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019160 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019161 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019162 { # dynamic, static and forwarded symbols
19163 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019164 if($IsNeededLib)
19165 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019166 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019167 {
19168 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19169 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019171 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019172 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 {
19174 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19175 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019176 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19177 {
19178 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19179 setLanguage($LibVersion, "C++");
19180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019182 }
19183 }
19184 }
19185 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019186
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019187 if($Deps)
19188 {
19189 if($LIB_TYPE eq "dynamic")
19190 { # dependencies
19191 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19192 while(<LIB>)
19193 {
19194 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19195 and $1 ne $Lib_Path) {
19196 $NeededLib{path_format($1, $OSgroup)} = 1;
19197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019198 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019199 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019201 }
19202 }
19203 else
19204 { # Unix; *.so, *.a
19205 # Symbian: *.dso, *.lib
19206 my $ReadelfCmd = get_CmdPath("readelf");
19207 if(not $ReadelfCmd) {
19208 exitStatus("Not_Found", "can't find \"readelf\"");
19209 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019210 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019211 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019212 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019213 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019214 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019215 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019216 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019217 else
19218 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019219 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019220 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019221 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 while(<LIB>)
19223 {
19224 if($LIB_TYPE eq "dynamic")
19225 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019226 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019227 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019228 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019229 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019230 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019231 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019232 # do nothing with symtab
19233 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019235 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019236 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019237 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019238 next;
19239 }
19240 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019241 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019243 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019244 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019245 if($CheckUndefined)
19246 {
19247 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019248 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019249 }
19250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 next;
19252 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019253 if($Bind eq "WEAK")
19254 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019255 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019256 if($Weak eq "-Weak")
19257 { # skip WEAK symbols
19258 next;
19259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019261 my $Short = $Symbol;
19262 $Short=~s/\@.+//g;
19263 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019264 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019265 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19266 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019267 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019268 if($IsNeededLib)
19269 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019270 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019271 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019272 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19273 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019275 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019276 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019277 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019278 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19279 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19280 if($Vers)
19281 {
19282 if($LIB_EXT eq "so")
19283 { # value
19284 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19285 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019287 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019288 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19289 {
19290 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19291 setLanguage($LibVersion, "C++");
19292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019294 }
19295 }
19296 }
19297 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019298
19299 if($Deps and $LIB_TYPE eq "dynamic")
19300 { # dynamic library specifics
19301 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19302 open(LIB, $Cmd." |");
19303
19304 while(<LIB>)
19305 {
19306 if(/NEEDED.+\[([^\[\]]+)\]/)
19307 { # dependencies:
19308 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19309 $NeededLib{$1} = 1;
19310 }
19311 }
19312
19313 close(LIB);
19314 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019315 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019316 if($Vers)
19317 {
19318 if(not $IsNeededLib and $LIB_EXT eq "so")
19319 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019320 my %Found = ();
19321
19322 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019323 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019324 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019325 next if(index($Symbol,"\@")==-1);
19326 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019327 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019328 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019329 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019330 if($Symbol_SameValue ne $Symbol
19331 and index($Symbol_SameValue,"\@")==-1)
19332 {
19333 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019334 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019335 last;
19336 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019337 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019338 }
19339 }
19340
19341 # default
19342 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19343 {
19344 next if(defined $Found{$Symbol});
19345 next if(index($Symbol,"\@\@")==-1);
19346
19347 if($Symbol=~/\A([^\@]*)\@\@/
19348 and not $SymVer{$LibVersion}{$1})
19349 {
19350 $SymVer{$LibVersion}{$1} = $Symbol;
19351 $Found{$Symbol} = 1;
19352 }
19353 }
19354
19355 # non-default
19356 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19357 {
19358 next if(defined $Found{$Symbol});
19359 next if(index($Symbol,"\@")==-1);
19360
19361 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19362 and not $SymVer{$LibVersion}{$1})
19363 {
19364 $SymVer{$LibVersion}{$1} = $Symbol;
19365 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019366 }
19367 }
19368 }
19369 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019370 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019371 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019372 foreach my $DyLib (sort keys(%NeededLib))
19373 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019374 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19375
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019376 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19377 {
19378 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19379 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19380 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019382 }
19383 }
19384 pop(@RecurLib);
19385 return $Library_Symbol{$LibVersion};
19386}
19387
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019388sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019389{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019391 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019392 return keys(%Prefixes);
19393}
19394
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019395sub get_prefixes_I($$)
19396{
19397 foreach my $P (@{$_[0]})
19398 {
19399 my @Parts = reverse(split(/[\/\\]+/, $P));
19400 my $Name = $Parts[0];
19401 foreach (1 .. $#Parts)
19402 {
19403 $_[1]->{$Name}{$P} = 1;
19404 last if($_>4 or $Parts[$_] eq "include");
19405 $Name = $Parts[$_].$SLASH.$Name;
19406 }
19407 }
19408}
19409
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019410sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019411{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019412 $Cache{"checkSystemFiles"} = 1;
19413
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019414 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019415
19416 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417 {
19418 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019419
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019420 my @Files = cmd_find($DevelPath,"f");
19421 foreach my $Link (cmd_find($DevelPath,"l"))
19422 { # add symbolic links
19423 if(-f $Link) {
19424 push(@Files, $Link);
19425 }
19426 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019427
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019428 # search for headers in /usr/lib
19429 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19430 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19431 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019432
19433 # search for libraries in /usr/lib (including symbolic links)
19434 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19435 foreach my $Path (@Libs)
19436 {
19437 my $N = get_filename($Path);
19438 $SystemObjects{$N}{$Path} = 1;
19439 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019440 }
19441 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019442
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019443 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019445 next if(not -d $DevelPath);
19446 # search for all header files in the /usr/include
19447 # with or without extension (ncurses.h, QtCore, ...)
19448 push(@SysHeaders, cmd_find($DevelPath,"f"));
19449 foreach my $Link (cmd_find($DevelPath,"l"))
19450 { # add symbolic links
19451 if(-f $Link) {
19452 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019453 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019454 }
19455 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019456 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019457}
19458
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019459sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019460{
19461 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019462 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019463 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19464 {
19465 if(not -e $Dest) {
19466 exitStatus("Access_Error", "can't access \'$Dest\'");
19467 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019468 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019469 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19470 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019471 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019472 }
19473 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019474 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019475}
19476
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019477sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019478{
19479 my ($Path, $LibVersion) = @_;
19480 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019481 my $Name = get_filename($Path);
19482 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019483 return 1;
19484 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019485 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019486 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19487 return 1;
19488 }
19489 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19490 {
19491 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19492 return 1;
19493 }
19494 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019495 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019496 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019497 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019498 return 1;
19499 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019500 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019501 return 1;
19502 }
19503 }
19504 return 0;
19505}
19506
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019507sub specificHeader($$)
19508{
19509 my ($Header, $Spec) = @_;
19510 my $Name = get_filename($Header);
19511
19512 if($Spec eq "windows")
19513 {# MS Windows
19514 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19515 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19516 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19517 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19518 my @Dirs = (
19519 "win32",
19520 "win64",
19521 "win",
19522 "windows",
19523 "msvcrt"
19524 ); # /gsf-win32/
19525 if(my $DIRs = join("|", @Dirs)) {
19526 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19527 }
19528 }
19529 elsif($Spec eq "macos")
19530 { # Mac OS
19531 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19532 }
19533
19534 return 0;
19535}
19536
19537sub skipAlienHeader($)
19538{
19539 my $Path = $_[0];
19540 my $Name = get_filename($Path);
19541 my $Dir = get_dirname($Path);
19542
19543 if($Tolerance=~/2/)
19544 { # 2 - skip internal headers
19545 my @Terms = (
19546 "p",
19547 "priv",
19548 "int",
19549 "impl",
19550 "implementation",
19551 "internal",
19552 "private",
19553 "old",
19554 "compat",
19555 "debug",
19556 "test",
19557 "gen"
19558 );
19559
19560 my @Dirs = (
19561 "private",
19562 "priv",
19563 "port",
19564 "impl",
19565 "internal",
19566 "detail",
19567 "details",
19568 "old",
19569 "compat",
19570 "debug",
19571 "config",
19572 "compiler",
19573 "platform",
19574 "test"
19575 );
19576
19577 if(my $TERMs = join("|", @Terms)) {
19578 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19579 }
19580 if(my $DIRs = join("|", @Dirs)) {
19581 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19582 }
19583
19584 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19585 }
19586
19587 if($Tolerance=~/1/)
19588 { # 1 - skip non-Linux headers
19589 if($OSgroup ne "windows")
19590 {
19591 if(specificHeader($Path, "windows")) {
19592 return 1;
19593 }
19594 }
19595 if($OSgroup ne "macos")
19596 {
19597 if(specificHeader($Path, "macos")) {
19598 return 1;
19599 }
19600 }
19601 }
19602
19603 # valid
19604 return 0;
19605}
19606
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019607sub skipHeader($$)
19608{
19609 my ($Path, $LibVersion) = @_;
19610 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019611 if(defined $Cache{"skipHeader"}{$Path}) {
19612 return $Cache{"skipHeader"}{$Path};
19613 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019614 if(defined $Tolerance and $Tolerance=~/1|2/)
19615 { # --tolerant
19616 if(skipAlienHeader($Path)) {
19617 return ($Cache{"skipHeader"}{$Path} = 1);
19618 }
19619 }
19620 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19621 return 0;
19622 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019623 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19624}
19625
19626sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019627{ # returns:
19628 # 1 - if header should NOT be included and checked
19629 # 2 - if header should NOT be included, but should be checked
19630 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019631 my $Name = get_filename($Path);
19632 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019633 return $Kind;
19634 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019635 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19636 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019638 if(index($Path, $D)!=-1)
19639 {
19640 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19641 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019643 }
19644 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019645 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19646 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019648 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19649 {
19650 if($Name=~/$P/) {
19651 return $Kind;
19652 }
19653 if($P=~/[\/\\]/ and $Path=~/$P/) {
19654 return $Kind;
19655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019656 }
19657 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659 return 0;
19660}
19661
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019662sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019663{
19664 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019665 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019666 { # system directory
19667 return;
19668 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019669 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019670 { # already registered
19671 return;
19672 }
19673 foreach my $Path (find_libs($Dir,"",1))
19674 {
19675 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019676 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019677 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019678 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019679 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19680}
19681
19682sub registerObject($$)
19683{
19684 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019685
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019686 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019687 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Mattias Ellert01e41222015-12-19 23:34:57 +010019688 if($OStarget=~/linux|bsd|gnu/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019689 {
19690 if(my $SONAME = getSONAME($Path)) {
19691 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19692 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019693 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019694 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19695 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019696 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019697
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019698 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019699 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019700 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019701 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019702 if($ObjArch ne getArch_GCC($LibVersion))
19703 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19704 $CheckedArch{$LibVersion} = 1;
19705 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 +040019706 }
19707 }
19708 }
19709}
19710
19711sub getArch_Object($)
19712{
19713 my $Path = $_[0];
19714
19715 my %MachineType = (
19716 "14C" => "x86",
19717 "8664" => "x86_64",
19718 "1C0" => "arm",
19719 "200" => "ia64"
19720 );
19721
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019722 my %ArchName = (
19723 "s390:31-bit" => "s390",
19724 "s390:64-bit" => "s390x",
19725 "powerpc:common" => "ppc32",
19726 "powerpc:common64" => "ppc64",
19727 "i386:x86-64" => "x86_64",
19728 "mips:3000" => "mips",
19729 "sparc:v8plus" => "sparcv9"
19730 );
19731
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019732 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019733 {
19734 my $DumpbinCmd = get_CmdPath("dumpbin");
19735 if(not $DumpbinCmd) {
19736 exitStatus("Not_Found", "can't find \"dumpbin\"");
19737 }
19738
19739 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19740 my $Out = `$Cmd`;
19741
19742 if($Out=~/(\w+)\smachine/)
19743 {
19744 if(my $Type = $MachineType{uc($1)})
19745 {
19746 return $Type;
19747 }
19748 }
19749 }
Mattias Ellert01e41222015-12-19 23:34:57 +010019750 elsif($OStarget=~/linux|bsd|gnu/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019751 {
19752 my $ObjdumpCmd = get_CmdPath("objdump");
19753 if(not $ObjdumpCmd) {
19754 exitStatus("Not_Found", "can't find \"objdump\"");
19755 }
19756
19757 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019758
19759 if($OSgroup eq "windows") {
19760 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19761 }
19762 else {
19763 $Cmd = "LANG=$LOCALE ".$Cmd;
19764 }
19765 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019766
19767 if($Out=~/architecture:\s+([\w\-\:]+)/)
19768 {
19769 my $Arch = $1;
19770 if($Arch=~s/\:(.+)//)
19771 {
19772 my $Suffix = $1;
19773
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019774 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019775 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019776 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019777 }
19778 }
19779
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019780 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019781 $Arch = "x86";
19782 }
19783
19784 if($Arch eq "x86-64") {
19785 $Arch = "x86_64";
19786 }
19787
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019788 if($Arch eq "ia64-elf64") {
19789 $Arch = "ia64";
19790 }
19791
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019792 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019793 }
19794 }
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019795 elsif($OStarget=~/macos/)
19796 {
19797 my $OtoolCmd = get_CmdPath("otool");
19798 if(not $OtoolCmd) {
19799 exitStatus("Not_Found", "can't find \"otool\"");
19800 }
19801
19802 my $Cmd = $OtoolCmd." -hv -arch all \"$Path\"";
19803 my $Out = qx/$Cmd/;
19804
19805 if($Out=~/X86_64/i) {
19806 return "x86_64";
19807 }
19808 elsif($Out=~/X86/i) {
19809 return "x86";
19810 }
19811 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019812 else
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019813 {
19814 exitStatus("Error", "Not implemented yet");
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019815 # TODO
19816 }
19817
19818 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019819}
19820
19821sub getSONAME($)
19822{
19823 my $Path = $_[0];
19824 return if(not $Path);
19825 if(defined $Cache{"getSONAME"}{$Path}) {
19826 return $Cache{"getSONAME"}{$Path};
19827 }
19828 my $ObjdumpCmd = get_CmdPath("objdump");
19829 if(not $ObjdumpCmd) {
19830 exitStatus("Not_Found", "can't find \"objdump\"");
19831 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019832 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019833 if($OSgroup eq "windows") {
19834 $SonameCmd .= " | find \"SONAME\"";
19835 }
19836 else {
19837 $SonameCmd .= " | grep SONAME";
19838 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019839 if(my $SonameInfo = `$SonameCmd`)
19840 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019841 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19842 return ($Cache{"getSONAME"}{$Path} = $1);
19843 }
19844 }
19845 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019846}
19847
19848sub getSOPaths_Dest($$)
19849{
19850 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019851 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019852 return ();
19853 }
19854 if(-f $Dest)
19855 {
19856 if(not parse_libname($Dest, "name", $OStarget)) {
19857 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19858 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019859 registerObject($Dest, $LibVersion);
19860 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019861 return ($Dest);
19862 }
19863 elsif(-d $Dest)
19864 {
19865 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019866 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019867 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019868 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19869 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019870 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019871 { # all files and symlinks that match the name of a library
19872 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19873 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019874 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019875 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019876 }
19877 }
19878 }
19879 else
19880 { # search for all files and symlinks
19881 foreach my $Path (find_libs($Dest,"",""))
19882 {
19883 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019884 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019885 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019886 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019887 }
19888 if($OSgroup eq "macos")
19889 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019890 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019891 {
19892 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019893 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019894 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019895 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19896 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019897 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019898 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019899 }
19900 }
19901 }
19902 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019903 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019904 }
19905 else {
19906 return ();
19907 }
19908}
19909
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019910sub isCyclical($$)
19911{
19912 my ($Stack, $Value) = @_;
19913 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019914}
19915
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019916sub getGCC_Opts($)
19917{ # to use in module
19918 my $LibVersion = $_[0];
19919
19920 my @Opts = ();
19921
19922 if($CompilerOptions{$LibVersion})
19923 { # user-defined options
19924 push(@Opts, $CompilerOptions{$LibVersion});
19925 }
19926 if($GccOptions)
19927 { # additional
19928 push(@Opts, $GccOptions);
19929 }
19930
19931 if(@Opts) {
19932 return join(" ", @Opts);
19933 }
19934
19935 return undef;
19936}
19937
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019938sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019939{
19940 my $LibVersion = $_[0];
19941
19942 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19943 return $Cache{"getArch_GCC"}{$LibVersion};
19944 }
19945
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019946 if(not $GCC_PATH) {
19947 return undef;
19948 }
19949
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019950 my $Arch = undef;
19951
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030019952 if(my $Target = get_dumpmachine($GCC_PATH))
19953 {
19954 if($Target=~/x86_64/) {
19955 $Arch = "x86_64";
19956 }
19957 elsif($Target=~/i[3-6]86/) {
19958 $Arch = "x86";
19959 }
19960 elsif($Target=~/\Aarm/i) {
19961 $Arch = "arm";
19962 }
19963 }
19964
19965 if(not $Arch)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019966 {
19967 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19968
19969 my $Cmd = $GCC_PATH." test.c -o test";
19970 if(my $Opts = getGCC_Opts($LibVersion))
19971 { # user-defined options
19972 $Cmd .= " ".$Opts;
19973 }
19974
19975 chdir($TMP_DIR);
19976 system($Cmd);
19977 chdir($ORIG_DIR);
19978
19979 $Arch = getArch_Object("$TMP_DIR/test");
19980
19981 unlink("$TMP_DIR/test.c");
19982 unlink("$TMP_DIR/test");
19983 }
19984
19985 if(not $Arch) {
19986 exitStatus("Error", "can't check ARCH type");
19987 }
19988
19989 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19990}
19991
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019992sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019993{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019994 my $LibVersion = $_[0];
19995
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019996 my $Size = undef;
19997
19998 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019999 if(my $Arch = getArch($LibVersion))
20000 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040020001 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020002 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020003 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020004 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
20005 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020006 }
20007 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020008
20009 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020010 {
20011 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020012
20013 my $Cmd = $GCC_PATH." -E -dD empty.h";
20014 if(my $Opts = getGCC_Opts($LibVersion))
20015 { # user-defined options
20016 $Cmd .= " ".$Opts;
20017 }
20018
20019 chdir($TMP_DIR);
20020 my $Defines = `$Cmd`;
20021 chdir($ORIG_DIR);
20022
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020023 unlink("$TMP_DIR/empty.h");
20024
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020025 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
20026 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020027 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020028 }
20029 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
20030 { # GCC 3
20031 my $PTRDIFF = $1;
20032 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020033 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020034 }
20035 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020036 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020037 }
20038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020039 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040020040
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020041 if(not $Size) {
20042 exitStatus("Error", "can't check WORD size");
20043 }
20044
20045 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020046}
20047
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040020048sub getWordSize($)
20049{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020050 return $WORD_SIZE{$_[0]};
20051}
20052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020053sub majorVersion($)
20054{
20055 my $V = $_[0];
20056 return 0 if(not $V);
20057 my @VParts = split(/\./, $V);
20058 return $VParts[0];
20059}
20060
20061sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020062{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020063 my ($V1, $V2) = @_;
20064 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 my @V1Parts = split(/\./, $V1);
20066 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020067 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
20068 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020069 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
20070 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
20071 }
20072 return -1 if($#V1Parts < $#V2Parts);
20073 return 1 if($#V1Parts > $#V2Parts);
20074 return 0;
20075}
20076
20077sub read_ABI_Dump($$)
20078{
20079 my ($LibVersion, $Path) = @_;
20080 return if(not $LibVersion or not -e $Path);
20081 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020082 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 { # input *.abi
20084 $FilePath = $Path;
20085 }
20086 else
20087 { # input *.abi.tar.gz
20088 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020089 if(not isDump_U($FilePath)) {
20090 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020092 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020093
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020094 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020095
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020096 my $Line = readLineNum($FilePath, 0);
20097 if($Line=~/xml/)
20098 { # XML format
20099 loadModule("XmlDump");
20100 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020101 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020102 else
20103 { # Perl Data::Dumper format (default)
20104 open(DUMP, $FilePath);
20105 local $/ = undef;
20106 my $Content = <DUMP>;
20107 close(DUMP);
20108
20109 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20110 { # remove temp file
20111 unlink($FilePath);
20112 }
20113 if($Content!~/};\s*\Z/) {
20114 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20115 }
20116 $ABI = eval($Content);
20117 if(not $ABI) {
20118 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020120 }
20121 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020122 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020123 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020124 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020125 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020126 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020127 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020128 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030020129 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020130
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020131 if($ABI->{"PublicABI"}) {
20132 $UsedDump{$LibVersion}{"Public"} = 1;
20133 }
20134
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020135 if($ABI->{"ABI_DUMP_VERSION"})
20136 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020137 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020138 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020139 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020140 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020141 }
20142 else
20143 { # support for old ABI dumps
20144 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020145 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020146 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020148 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020149
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020150 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020151 {
20152 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 +040020153 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020154
20155 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20156 { # DWARF ABI Dump
20157 $UseConv_Real{$LibVersion}{"P"} = 1;
20158 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20159
20160 $UsedDump{$LibVersion}{"DWARF"} = 1;
20161
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030020162 if(not $TargetComponent_Opt)
20163 {
20164 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
20165 $TargetComponent = "module";
20166 }
20167 else {
20168 $TargetComponent = "object";
20169 }
20170 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020171 }
20172
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020173 if(not checkDump($LibVersion, "2.11"))
20174 { # old ABI dumps
20175 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020176 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020177 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020178 { # ABI dump created with --binary option
20179 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20180 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020181 else
20182 { # default
20183 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20184 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020185
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020186 if(defined $ABI->{"Mode"}
20187 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020188 { # --ext option
20189 $ExtendedCheck = 1;
20190 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020191 if($ABI->{"Extra"}) {
20192 $ExtraDump = 1;
20193 }
20194
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020195 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020196 {
20197 $UsedDump{$LibVersion}{"L"} = $Lang;
20198 setLanguage($LibVersion, $Lang);
20199 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020200 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020201 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020202 }
20203 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020204 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020205 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020206 if(not $TInfo)
20207 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020208 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020209 }
20210 my %Tid_TDid = ();
20211 foreach my $TDid (keys(%{$TInfo}))
20212 {
20213 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20214 {
20215 $MAX_ID = $Tid if($Tid>$MAX_ID);
20216 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020217 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020218 }
20219 }
20220 my %NewID = ();
20221 foreach my $Tid (keys(%Tid_TDid))
20222 {
20223 my @TDids = keys(%{$Tid_TDid{$Tid}});
20224 if($#TDids>=1)
20225 {
20226 foreach my $TDid (@TDids)
20227 {
20228 if($TDid) {
20229 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20230 }
20231 else
20232 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020233 my $ID = ++$MAX_ID;
20234
20235 $NewID{$TDid}{$Tid} = $ID;
20236 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20237 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020238 }
20239 }
20240 }
20241 else
20242 {
20243 my $TDid = $TDids[0];
20244 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20245 }
20246 }
20247 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20248 {
20249 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20250 if(defined $Info{"BaseType"})
20251 {
20252 my $Bid = $Info{"BaseType"}{"Tid"};
20253 my $BDid = $Info{"BaseType"}{"TDid"};
20254 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020255 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020256 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20257 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20258 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020259 }
20260 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020263 read_Machine_DumpInfo($ABI, $LibVersion);
20264 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020265 if(not $SymbolInfo{$LibVersion})
20266 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268 }
20269 if(not keys(%{$SymbolInfo{$LibVersion}}))
20270 { # validation of old-version dumps
20271 if(not $ExtendedCheck) {
20272 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20273 }
20274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020275 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020276 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020278 else
20279 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020280 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020281 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020282 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020283 }
20284 if(not $DepSymbols)
20285 { # Cannot reconstruct DepSymbols. This may result in false
20286 # positives if the old dump is for library 2. Not a problem if
20287 # old dumps are only from old libraries.
20288 $DepSymbols = {};
20289 }
20290 foreach my $Symbol (keys(%{$DepSymbols})) {
20291 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20292 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020293 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020294 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020295
20296 if(my $V = $TargetVersion{$LibVersion}) {
20297 $Descriptor{$LibVersion}{"Version"} = $V;
20298 }
20299 else {
20300 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20301 }
20302
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020303 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020304 { # if not defined by -skip-types option
20305 if(defined $ABI->{"SkipTypes"})
20306 {
20307 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20308 {
20309 $SkipTypes{$LibVersion}{$TName} = 1;
20310 }
20311 }
20312 if(defined $ABI->{"OpaqueTypes"})
20313 { # support for old dumps
20314 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20315 {
20316 $SkipTypes{$LibVersion}{$TName} = 1;
20317 }
20318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020319 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020320
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020321 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020322 { # if not defined by -skip-symbols option
20323 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20324 if(not $SkipSymbols{$LibVersion})
20325 { # support for old dumps
20326 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20327 }
20328 if(not $SkipSymbols{$LibVersion})
20329 { # support for old dumps
20330 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020332 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020333 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020334
20335 if(not $TargetHeaders{$LibVersion})
20336 { # if not defined by -headers-list option
20337 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20338 }
20339
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020340 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020341 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020342 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030020343
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020344 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020345 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020347
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020348 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020349 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020350
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020351 if(not checkDump($LibVersion, "2.10.1")
20352 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020353 { # support for old ABI dumps: added target headers
20354 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020355 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020356 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020357
20358 if(not $ABI->{"PublicABI"})
20359 {
20360 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20361 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20362 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020364 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020365 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020366 if(defined $ABI->{"GccConstants"})
20367 { # 3.0
20368 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20369 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20370 }
20371 }
20372
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020373 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020374 if(not $NestedNameSpaces{$LibVersion})
20375 { # support for old dumps
20376 # Cannot reconstruct NameSpaces. This may affect design
20377 # of the compatibility report.
20378 $NestedNameSpaces{$LibVersion} = {};
20379 }
20380 # target system type
20381 # needed to adopt HTML report
20382 if(not $DumpSystem)
20383 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020384 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020385 }
20386 # recreate environment
20387 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20388 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020389 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020390 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020391 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20392 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020394 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020395 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020396 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20397 {
20398 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20399 setLanguage($LibVersion, "C++");
20400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020401 }
20402 }
20403 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020404 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20405 {
20406 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20407 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20408 }
20409 }
20410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020411 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020412 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020413 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020414 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020415 {
20416 if(not $Symbol_Library{$LibVersion}{$MnglName}
20417 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20418 push(@VFunc, $MnglName);
20419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020420 }
20421 }
20422 translateSymbols(@VFunc, $LibVersion);
20423 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020424 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20425
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020426 if(not checkDump($LibVersion, "3.0"))
20427 { # support for old ABI dumps
20428 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20429 {
20430 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20431 {
20432 if(ref($BaseType) eq "HASH") {
20433 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20434 }
20435 }
20436 }
20437 }
20438
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020439 if(not checkDump($LibVersion, "3.2"))
20440 { # support for old ABI dumps
20441 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20442 {
20443 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20444 {
20445 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20446 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20447 }
20448 }
20449 }
20450
20451 # repair target headers list
20452 delete($TargetHeaders{$LibVersion});
20453 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020454 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20455 }
20456 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20457 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020458 }
20459
20460 # non-target constants from anon enums
20461 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20462 {
20463 if(not $ExtraDump
20464 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20465 {
20466 delete($Constants{$LibVersion}{$Name});
20467 }
20468 }
20469 }
20470
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020471 if(not checkDump($LibVersion, "2.20"))
20472 { # support for old ABI dumps
20473 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20474 {
20475 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20476
20477 if($TType=~/Struct|Union|Enum|Typedef/)
20478 { # repair complex types first
20479 next;
20480 }
20481
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020482 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020483 {
20484 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20485 if($BType=~/Struct|Union|Enum/i)
20486 {
20487 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20488 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20489 }
20490 }
20491 }
20492 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20493 {
20494 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20495 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20496 if($TType=~/Struct|Union|Enum/) {
20497 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20498 }
20499 }
20500 }
20501
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020502 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020503 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020504 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20505 { # support for old ABI dumps < 2.0 (ACC 1.22)
20506 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20507 {
20508 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20509 {
20510 if($Access ne "public") {
20511 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20512 }
20513 }
20514 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20515 }
20516 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20517 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020518 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20519 { # support for old ABI dumps
20520 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20521 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020522 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20523 { # DWARF ABI Dumps
20524 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20525 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020526 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20527 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20528 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020529
20530 # support for old formatting of type names
20531 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20532
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020533 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20534 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020535 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020536 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20537 {
20538 if($SubId eq $TypeId)
20539 { # Fix erroneus ABI dump
20540 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20541 next;
20542 }
20543
20544 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020545 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020546 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020547 if($TInfo{"Type"} eq "MethodPtr")
20548 {
20549 if(defined $TInfo{"Param"})
20550 { # support for old ABI dumps <= 1.17
20551 if(not defined $TInfo{"Param"}{"0"})
20552 {
20553 my $Max = keys(%{$TInfo{"Param"}});
20554 foreach my $Pos (1 .. $Max) {
20555 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20556 }
20557 delete($TInfo{"Param"}{$Max});
20558 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20559 }
20560 }
20561 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020562 if($TInfo{"BaseType"} eq $TypeId)
20563 { # fix ABI dump
20564 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20565 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020566
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020567 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020568 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020569 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020570 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020571 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20572 if(not $BName)
20573 { # broken type
20574 next;
20575 }
20576 if($TInfo{"Name"} eq $BName)
20577 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020578 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020579 next;
20580 }
20581 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20582 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020583 }
20584 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020585 }
20586 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20587 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020588 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020589 }
20590 }
20591
20592 if(not checkDump($LibVersion, "2.15"))
20593 { # support for old ABI dumps
20594 my %Dups = ();
20595 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20596 {
20597 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020598 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020599 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20600 { # remove template decls
20601 delete($SymbolInfo{$LibVersion}{$InfoId});
20602 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020604 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020605 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20606 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020607 { # templates
20608 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020609 }
20610 }
20611 }
20612
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020613 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20614 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020615 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20616 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20617 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20618 { # support for old ABI dumps (< 3.1)
20619 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20620 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20621 { # add "this" first parameter
20622 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20623 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20624
20625 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20626 {
20627 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20628 foreach my $Pos (reverse(0 .. $#Pos)) {
20629 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20630 }
20631 }
20632 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20633 }
20634 }
20635
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020636 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20637 { # ABI dumps have no mangled names for C-functions
20638 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20639 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020640 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20641 { # support for old ABI dumps
20642 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20643 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020644 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20645 { # DWARF ABI Dumps
20646 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20647 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020648 }
20649
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020650 $Descriptor{$LibVersion}{"Dump"} = 1;
20651}
20652
20653sub read_Machine_DumpInfo($$)
20654{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020655 my ($ABI, $LibVersion) = @_;
20656 if($ABI->{"Arch"}) {
20657 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020658 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020659 if($ABI->{"WordSize"}) {
20660 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020661 }
20662 else
20663 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020664 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 }
20666 if(not $WORD_SIZE{$LibVersion})
20667 { # support for old dumps (<1.23)
20668 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20669 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020670 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020671 }
20672 else
20673 {
20674 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020675 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020676 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020677 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20678 { # any "pointer"-type
20679 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020680 last;
20681 }
20682 }
20683 if($PSize)
20684 { # a pointer type size
20685 $WORD_SIZE{$LibVersion} = $PSize;
20686 }
20687 else {
20688 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20689 }
20690 }
20691 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020692 if($ABI->{"GccVersion"}) {
20693 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020694 }
20695}
20696
20697sub read_Libs_DumpInfo($$)
20698{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020699 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020700 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20701 if(not $Library_Symbol{$LibVersion})
20702 { # support for old dumps
20703 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020705 if(keys(%{$Library_Symbol{$LibVersion}})
20706 and not $DumpAPI) {
20707 $Descriptor{$LibVersion}{"Libs"} = "OK";
20708 }
20709}
20710
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020711sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020712{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020713 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020714
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020715 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020716 and not $DumpAPI) {
20717 $Descriptor{$LibVersion}{"Headers"} = "OK";
20718 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020719 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020720 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020721 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020722 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020723 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020724
20725 if(keys(%{$ABI->{"Sources"}})
20726 and not $DumpAPI) {
20727 $Descriptor{$LibVersion}{"Sources"} = "OK";
20728 }
20729 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020730 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020731 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20732 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020734}
20735
20736sub find_libs($$$)
20737{
20738 my ($Path, $Type, $MaxDepth) = @_;
20739 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020740 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020741}
20742
20743sub createDescriptor($$)
20744{
20745 my ($LibVersion, $Path) = @_;
20746 if(not $LibVersion or not $Path
20747 or not -e $Path) {
20748 return "";
20749 }
20750 if(-d $Path)
20751 { # directory with headers files and shared objects
20752 return "
20753 <version>
20754 ".$TargetVersion{$LibVersion}."
20755 </version>
20756
20757 <headers>
20758 $Path
20759 </headers>
20760
20761 <libs>
20762 $Path
20763 </libs>";
20764 }
20765 else
20766 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020767 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020768 { # standard XML-descriptor
20769 return readFile($Path);
20770 }
20771 elsif(is_header($Path, 2, $LibVersion))
20772 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020773 $CheckHeadersOnly = 1;
20774
20775 if($LibVersion==1) {
20776 $TargetVersion{$LibVersion} = "X";
20777 }
20778
20779 if($LibVersion==2) {
20780 $TargetVersion{$LibVersion} = "Y";
20781 }
20782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020783 return "
20784 <version>
20785 ".$TargetVersion{$LibVersion}."
20786 </version>
20787
20788 <headers>
20789 $Path
20790 </headers>
20791
20792 <libs>
20793 none
20794 </libs>";
20795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 else
20797 { # standard XML-descriptor
20798 return readFile($Path);
20799 }
20800 }
20801}
20802
20803sub detect_lib_default_paths()
20804{
20805 my %LPaths = ();
20806 if($OSgroup eq "bsd")
20807 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020808 if(my $LdConfig = get_CmdPath("ldconfig"))
20809 {
20810 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20811 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020812 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20813 {
20814 my $Name = "lib".$1;
20815 if(not defined $LPaths{$Name}) {
20816 $LPaths{$Name} = $2;
20817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020818 }
20819 }
20820 }
20821 else {
20822 printMsg("WARNING", "can't find ldconfig");
20823 }
20824 }
20825 else
20826 {
20827 if(my $LdConfig = get_CmdPath("ldconfig"))
20828 {
20829 if($SystemRoot and $OSgroup eq "linux")
20830 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20831 if(-e $SystemRoot."/etc/ld.so.conf") {
20832 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20833 }
20834 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020835 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20836 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020837 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20838 {
20839 my ($Name, $Path) = ($1, $2);
20840 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020841 if(not defined $LPaths{$Name})
20842 { # get first element from the list of available paths
20843
20844 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20845 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20846 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20847
20848 $LPaths{$Name} = $Path;
20849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020850 }
20851 }
20852 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020853 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020854 printMsg("WARNING", "can't find ldconfig");
20855 }
20856 }
20857 return \%LPaths;
20858}
20859
20860sub detect_bin_default_paths()
20861{
20862 my $EnvPaths = $ENV{"PATH"};
20863 if($OSgroup eq "beos") {
20864 $EnvPaths.=":".$ENV{"BETOOLS"};
20865 }
20866 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020867 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020868 {
20869 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020870 next if(not $Path);
20871 if($SystemRoot
20872 and $Path=~/\A\Q$SystemRoot\E\//)
20873 { # do NOT use binaries from target system
20874 next;
20875 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020876 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020877 }
20878}
20879
20880sub detect_inc_default_paths()
20881{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020882 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020884 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020885 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020886 next if(index($Line, "/cc1plus ")!=-1);
20887
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020888 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20889 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020890 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020892 if(index($Path, "c++")!=-1
20893 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020895 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020896 if(not defined $MAIN_CPP_DIR
20897 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20898 $MAIN_CPP_DIR = $Path;
20899 }
20900 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020901 elsif(index($Path, "gcc")!=-1) {
20902 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020903 }
20904 else
20905 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020906 if($Path=~/local[\/\\]+include/)
20907 { # local paths
20908 next;
20909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020910 if($SystemRoot
20911 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20912 { # The GCC include path for user headers is not a part of the system root
20913 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20914 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20915 next;
20916 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020917 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020918 }
20919 }
20920 }
20921 unlink("$TMP_DIR/empty.h");
20922 return %DPaths;
20923}
20924
20925sub detect_default_paths($)
20926{
20927 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20928 my $Search = $_[0];
20929 if($Search!~/inc/) {
20930 $HSearch = 0;
20931 }
20932 if($Search!~/lib/) {
20933 $LSearch = 0;
20934 }
20935 if($Search!~/bin/) {
20936 $BSearch = 0;
20937 }
20938 if($Search!~/gcc/) {
20939 $GSearch = 0;
20940 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020941 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020942 { # <search_headers> section of the XML descriptor
20943 # do NOT search for systems headers
20944 $HSearch = 0;
20945 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020946 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020947 { # <search_libs> section of the XML descriptor
20948 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949 $LSearch = 0;
20950 }
20951 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20952 { # additional search paths
20953 next if($Type eq "include" and not $HSearch);
20954 next if($Type eq "lib" and not $LSearch);
20955 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020956 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020957 }
20958 if($OSgroup ne "windows")
20959 { # unix-like
20960 foreach my $Type ("include", "lib", "bin")
20961 { # automatic detection of system "devel" directories
20962 next if($Type eq "include" and not $HSearch);
20963 next if($Type eq "lib" and not $LSearch);
20964 next if($Type eq "bin" and not $BSearch);
20965 my ($UsrDir, $RootDir) = ("/usr", "/");
20966 if($SystemRoot and $Type ne "bin")
20967 { # 1. search for target headers and libraries
20968 # 2. use host commands: ldconfig, readelf, etc.
20969 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20970 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020971 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020972 if(-d $RootDir."/".$Type)
20973 { # if "/lib" is symbolic link
20974 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020975 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 }
20977 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020978 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 }
20980 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020981 if(-d $UsrDir)
20982 {
20983 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020984 if(-d $UsrDir."/".$Type)
20985 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020986 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987 }
20988 }
20989 }
20990 }
20991 if($BSearch)
20992 {
20993 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020994 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020995 }
20996 # check environment variables
20997 if($OSgroup eq "beos")
20998 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020999 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021000 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021001 if($_ eq ".") {
21002 next;
21003 }
21004 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
21005 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
21006 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021007 }
21008 }
21009 if($HSearch)
21010 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021011 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
21012 split(/:|;/, $ENV{"BEINCLUDES"})
21013 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021014 }
21015 if($LSearch)
21016 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021017 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
21018 split(/:|;/, $ENV{"BELIBRARIES"}),
21019 split(/:|;/, $ENV{"LIBRARY_PATH"})
21020 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021021 }
21022 }
21023 if($LSearch)
21024 { # using linker to get system paths
21025 if(my $LPaths = detect_lib_default_paths())
21026 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021027 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028 foreach my $Name (keys(%{$LPaths}))
21029 {
21030 if($SystemRoot
21031 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
21032 { # wrong ldconfig configuration
21033 # check your <sysroot>/etc/ld.so.conf
21034 next;
21035 }
21036 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021037 if(my $Dir = get_dirname($LPaths->{$Name})) {
21038 $Dirs{$Dir} = 1;
21039 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021040 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021041 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021043 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021044 }
21045 if($BSearch)
21046 {
21047 if($CrossGcc)
21048 { # --cross-gcc=arm-linux-gcc
21049 if(-e $CrossGcc)
21050 { # absolute or relative path
21051 $GCC_PATH = get_abs_path($CrossGcc);
21052 }
21053 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
21054 { # command name
21055 $GCC_PATH = $CrossGcc;
21056 }
21057 else {
21058 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
21059 }
21060 if($GCC_PATH=~/\s/) {
21061 $GCC_PATH = "\"".$GCC_PATH."\"";
21062 }
21063 }
21064 }
21065 if($GSearch)
21066 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021067 if(not $CrossGcc)
21068 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021069 $GCC_PATH = get_CmdPath("gcc");
21070 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021071 if(not $GCC_PATH)
21072 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021073 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021074 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021075 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021076 { # select the latest version
21077 @GCCs = sort {$b cmp $a} @GCCs;
21078 if(check_gcc($GCCs[0], "3"))
21079 {
21080 $GCC_PATH = $GCCs[0];
21081 last;
21082 }
21083 }
21084 }
21085 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021086 if(not $GCC_PATH) {
21087 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
21088 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040021089
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021090 my $GCC_Ver = get_dumpversion($GCC_PATH);
21091 if($GCC_Ver eq "4.8")
21092 { # on Ubuntu -dumpversion returns 4.8 for gcc 4.8.4
21093 my $Info = `$GCC_PATH --version`;
21094
21095 if($Info=~/gcc\s+(|\([^()]+\)\s+)(\d+\.\d+\.\d+)/)
21096 { # gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
21097 # gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6)
21098 $GCC_Ver = $2;
21099 }
21100 }
21101
Andrey Ponomarenko737aef52016-05-06 15:08:08 +030021102 if($OStarget=~/macos/)
21103 {
21104 my $Info = `$GCC_PATH --version`;
21105
21106 if($Info=~/clang/i) {
21107 printMsg("WARNING", "doesn't work with clang, please install GCC instead (and select it by -gcc-path option)");
21108 }
21109 }
21110
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021111 if($GCC_Ver)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021112 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021113 my $GccTarget = get_dumpmachine($GCC_PATH);
21114
21115 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021116 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021117 $OStarget = "linux";
21118 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021119 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021120 elsif($GccTarget=~/symbian/)
21121 {
21122 $OStarget = "symbian";
21123 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
21124 }
21125
21126 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
21127
21128 # check GCC version
21129 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
21130 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko8a4c3f82016-02-21 03:45:16 +030021131 # introduced in 4.8 and fixed in 4.8.3
21132 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.");
21133
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021134 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021135 }
21136 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021137 else {
21138 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021139 }
21140 }
21141 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021142 {
21143 # GCC standard paths
21144 if($GCC_PATH and not $NoStdInc)
21145 {
21146 my %DPaths = detect_inc_default_paths();
21147 @DefaultCppPaths = @{$DPaths{"Cpp"}};
21148 @DefaultGccPaths = @{$DPaths{"Gcc"}};
21149 @DefaultIncPaths = @{$DPaths{"Inc"}};
21150 push_U($SystemPaths{"include"}, @DefaultIncPaths);
21151 }
21152
21153 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021154 my $IncPath = "/usr/include";
21155 if($SystemRoot) {
21156 $IncPath = $SystemRoot.$IncPath;
21157 }
21158 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021159 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021160 }
21161 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021162
21163 if($ExtraInfo)
21164 {
21165 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21166 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021168}
21169
21170sub getLIB_EXT($)
21171{
21172 my $Target = $_[0];
21173 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21174 return $Ext;
21175 }
21176 return $OS_LibExt{$LIB_TYPE}{"default"};
21177}
21178
21179sub getAR_EXT($)
21180{
21181 my $Target = $_[0];
21182 if(my $Ext = $OS_Archive{$Target}) {
21183 return $Ext;
21184 }
21185 return $OS_Archive{"default"};
21186}
21187
21188sub get_dumpversion($)
21189{
21190 my $Cmd = $_[0];
21191 return "" if(not $Cmd);
21192 if($Cache{"get_dumpversion"}{$Cmd}) {
21193 return $Cache{"get_dumpversion"}{$Cmd};
21194 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021195 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021196 chomp($V);
21197 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21198}
21199
21200sub get_dumpmachine($)
21201{
21202 my $Cmd = $_[0];
21203 return "" if(not $Cmd);
21204 if($Cache{"get_dumpmachine"}{$Cmd}) {
21205 return $Cache{"get_dumpmachine"}{$Cmd};
21206 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021207 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021208 chomp($Machine);
21209 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21210}
21211
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021212sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021213{
21214 my $Cmd = $_[0];
21215 return "" if(not $Cmd);
21216 my @Options = (
21217 "--version",
21218 "-help"
21219 );
21220 foreach my $Opt (@Options)
21221 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021222 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021223 if($Info) {
21224 return 1;
21225 }
21226 }
21227 return 0;
21228}
21229
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021230sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021231{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021232 my ($Cmd, $ReqVer) = @_;
21233 return 0 if(not $Cmd or not $ReqVer);
21234 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21235 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021236 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021237 if(my $GccVer = get_dumpversion($Cmd))
21238 {
21239 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21240 if(cmpVersions($GccVer, $ReqVer)>=0) {
21241 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21242 }
21243 }
21244 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021245}
21246
21247sub get_depth($)
21248{
21249 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021250 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021251 }
21252 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21253}
21254
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021255sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021256{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021257 return if($Cache{"registerGccHeaders"}); # this function should be called once
21258
21259 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021260 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021261 my @Headers = cmd_find($Path,"f");
21262 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21263 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021264 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021265 my $FileName = get_filename($HPath);
21266 if(not defined $DefaultGccHeader{$FileName})
21267 { # skip duplicated
21268 $DefaultGccHeader{$FileName} = $HPath;
21269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021270 }
21271 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021272 $Cache{"registerGccHeaders"} = 1;
21273}
21274
21275sub registerCppHeaders()
21276{
21277 return if($Cache{"registerCppHeaders"}); # this function should be called once
21278
21279 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021280 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021281 my @Headers = cmd_find($CppDir,"f");
21282 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21283 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021284 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021285 my $FileName = get_filename($Path);
21286 if(not defined $DefaultCppHeader{$FileName})
21287 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021288 $DefaultCppHeader{$FileName} = $Path;
21289 }
21290 }
21291 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021292 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021293}
21294
21295sub parse_libname($$$)
21296{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021297 return "" if(not $_[0]);
21298 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21299 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021300 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021301 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21302}
21303
21304sub parse_libname_I($$$)
21305{
21306 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308 if($Target eq "symbian") {
21309 return parse_libname_symbian($Name, $Type);
21310 }
21311 elsif($Target eq "windows") {
21312 return parse_libname_windows($Name, $Type);
21313 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021314
21315 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021316 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021317 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021318 { # libSDL-1.2.so.0.7.1
21319 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021320 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021321 if($Type eq "name")
21322 { # libSDL-1.2
21323 # libwbxml2
21324 return $2;
21325 }
21326 elsif($Type eq "name+ext")
21327 { # libSDL-1.2.so
21328 # libwbxml2.so
21329 return $1;
21330 }
21331 elsif($Type eq "version")
21332 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021333 if(defined $7
21334 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021335 { # 0.7.1
21336 return $7;
21337 }
21338 else
21339 { # libc-2.5.so (=>2.5 version)
21340 my $MV = $5;
21341 $MV=~s/\A[\-\_]+//g;
21342 return $MV;
21343 }
21344 }
21345 elsif($Type eq "short")
21346 { # libSDL
21347 # libwbxml2
21348 return $3;
21349 }
21350 elsif($Type eq "shortest")
21351 { # SDL
21352 # wbxml
21353 return shortest_name($3);
21354 }
21355 }
21356 return "";# error
21357}
21358
21359sub parse_libname_symbian($$)
21360{
21361 my ($Name, $Type) = @_;
21362 my $Ext = getLIB_EXT("symbian");
21363 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21364 { # libpthread{00010001}.dso
21365 if($Type eq "name")
21366 { # libpthread{00010001}
21367 return $2;
21368 }
21369 elsif($Type eq "name+ext")
21370 { # libpthread{00010001}.dso
21371 return $1;
21372 }
21373 elsif($Type eq "version")
21374 { # 00010001
21375 my $V = $4;
21376 $V=~s/\{(.+)\}/$1/;
21377 return $V;
21378 }
21379 elsif($Type eq "short")
21380 { # libpthread
21381 return $3;
21382 }
21383 elsif($Type eq "shortest")
21384 { # pthread
21385 return shortest_name($3);
21386 }
21387 }
21388 return "";# error
21389}
21390
21391sub parse_libname_windows($$)
21392{
21393 my ($Name, $Type) = @_;
21394 my $Ext = getLIB_EXT("windows");
21395 if($Name=~/((.+?)\.$Ext)\Z/)
21396 { # netapi32.dll
21397 if($Type eq "name")
21398 { # netapi32
21399 return $2;
21400 }
21401 elsif($Type eq "name+ext")
21402 { # netapi32.dll
21403 return $1;
21404 }
21405 elsif($Type eq "version")
21406 { # DLL version embedded
21407 # at binary-level
21408 return "";
21409 }
21410 elsif($Type eq "short")
21411 { # netapi32
21412 return $2;
21413 }
21414 elsif($Type eq "shortest")
21415 { # netapi
21416 return shortest_name($2);
21417 }
21418 }
21419 return "";# error
21420}
21421
21422sub shortest_name($)
21423{
21424 my $Name = $_[0];
21425 # remove prefix
21426 $Name=~s/\A(lib|open)//;
21427 # remove suffix
21428 $Name=~s/[\W\d_]+\Z//i;
21429 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21430 return $Name;
21431}
21432
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021433sub createSymbolsList($$$$$)
21434{
21435 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021437 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021438 prepareSymbols(1);
21439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021440 my %SymbolHeaderLib = ();
21441 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021443 # Get List
21444 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21445 {
21446 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021447 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021448 next;
21449 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021450 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021451 { # skip other symbols
21452 next;
21453 }
21454 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21455 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021456 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021457 next;
21458 }
21459 my $DyLib = $Symbol_Library{1}{$Symbol};
21460 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021461 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021462 next;
21463 }
21464 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21465 $Total+=1;
21466 }
21467 # Draw List
21468 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21469 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21470 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21471 {
21472 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21473 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021474 my %NS_Symbol = ();
21475 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021476 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021477 }
21478 foreach my $NameSpace (sort keys(%NS_Symbol))
21479 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021480 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021481 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21482 foreach my $Symbol (@SortedInterfaces)
21483 {
21484 my $SubReport = "";
21485 my $Signature = get_Signature($Symbol, 1);
21486 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021487 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021488 }
21489 if($Symbol=~/\A(_Z|\?)/)
21490 {
21491 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021492 $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 +040021493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021494 else {
21495 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21496 }
21497 }
21498 else
21499 {
21500 if($Signature) {
21501 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21502 }
21503 else {
21504 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21505 }
21506 }
21507 $SYMBOLS_LIST .= $SubReport;
21508 }
21509 }
21510 $SYMBOLS_LIST .= "<br/>\n";
21511 }
21512 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021513 # clear info
21514 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21515 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21516 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21517 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021518 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021519 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021520 my $CssStyles = readModule("Styles", "SymbolsList.css");
21521 my $JScripts = readModule("Scripts", "Sections.js");
21522 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021523 my $Title = "$LName: public symbols";
21524 my $Keywords = "$LName, API, symbols";
21525 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021526 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021527 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021528 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021529 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021530 writeFile($SaveTo, $SYMBOLS_LIST);
21531}
21532
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021533sub add_target_libs($)
21534{
21535 foreach (@{$_[0]}) {
21536 $TargetLibs{$_} = 1;
21537 }
21538}
21539
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021540sub is_target_lib($)
21541{
21542 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021543 if(not $LName) {
21544 return 0;
21545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021546 if($TargetLibraryName
21547 and $LName!~/\Q$TargetLibraryName\E/) {
21548 return 0;
21549 }
21550 if(keys(%TargetLibs)
21551 and not $TargetLibs{$LName}
21552 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21553 return 0;
21554 }
21555 return 1;
21556}
21557
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021558sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021559{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021560 my ($H, $V) = @_;
21561 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021562 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021563 if($TargetHeaders{$V}{$H}) {
21564 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021565 }
21566 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021567 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021568}
21569
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021570sub readLibs($)
21571{
21572 my $LibVersion = $_[0];
21573 if($OStarget eq "windows")
21574 { # dumpbin.exe will crash
21575 # without VS Environment
21576 check_win32_env();
21577 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021578 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021579 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021580 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021581}
21582
21583sub dump_sorting($)
21584{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021585 my $Hash = $_[0];
21586 return [] if(not $Hash);
21587 my @Keys = keys(%{$Hash});
21588 return [] if($#Keys<0);
21589 if($Keys[0]=~/\A\d+\Z/)
21590 { # numbers
21591 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021592 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021593 else
21594 { # strings
21595 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021596 }
21597}
21598
21599sub printMsg($$)
21600{
21601 my ($Type, $Msg) = @_;
21602 if($Type!~/\AINFO/) {
21603 $Msg = $Type.": ".$Msg;
21604 }
21605 if($Type!~/_C\Z/) {
21606 $Msg .= "\n";
21607 }
21608 if($Quiet)
21609 { # --quiet option
21610 appendFile($COMMON_LOG_PATH, $Msg);
21611 }
21612 else
21613 {
21614 if($Type eq "ERROR") {
21615 print STDERR $Msg;
21616 }
21617 else {
21618 print $Msg;
21619 }
21620 }
21621}
21622
21623sub exitStatus($$)
21624{
21625 my ($Code, $Msg) = @_;
21626 printMsg("ERROR", $Msg);
21627 exit($ERROR_CODE{$Code});
21628}
21629
21630sub exitReport()
21631{ # the tool has run without any errors
21632 printReport();
21633 if($COMPILE_ERRORS)
21634 { # errors in headers may add false positives/negatives
21635 exit($ERROR_CODE{"Compile_Error"});
21636 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021637 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21638 { # --binary
21639 exit($ERROR_CODE{"Incompatible"});
21640 }
21641 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21642 { # --source
21643 exit($ERROR_CODE{"Incompatible"});
21644 }
21645 elsif($RESULT{"Source"}{"Problems"}
21646 or $RESULT{"Binary"}{"Problems"})
21647 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021648 exit($ERROR_CODE{"Incompatible"});
21649 }
21650 else {
21651 exit($ERROR_CODE{"Compatible"});
21652 }
21653}
21654
21655sub readRules($)
21656{
21657 my $Kind = $_[0];
21658 if(not -f $RULES_PATH{$Kind}) {
21659 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21660 }
21661 my $Content = readFile($RULES_PATH{$Kind});
21662 while(my $Rule = parseTag(\$Content, "rule"))
21663 {
21664 my $RId = parseTag(\$Rule, "id");
21665 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21666 foreach my $Prop (@Properties) {
21667 if(my $Value = parseTag(\$Rule, lc($Prop)))
21668 {
21669 $Value=~s/\n[ ]*//;
21670 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21671 }
21672 }
21673 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21674 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21675 }
21676 else {
21677 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21678 }
21679 }
21680}
21681
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021682sub getReportPath($)
21683{
21684 my $Level = $_[0];
21685 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21686 if($Level eq "Binary")
21687 {
21688 if($BinaryReportPath)
21689 { # --bin-report-path
21690 return $BinaryReportPath;
21691 }
21692 elsif($OutputReportPath)
21693 { # --report-path
21694 return $OutputReportPath;
21695 }
21696 else
21697 { # default
21698 return $Dir."/abi_compat_report.$ReportFormat";
21699 }
21700 }
21701 elsif($Level eq "Source")
21702 {
21703 if($SourceReportPath)
21704 { # --src-report-path
21705 return $SourceReportPath;
21706 }
21707 elsif($OutputReportPath)
21708 { # --report-path
21709 return $OutputReportPath;
21710 }
21711 else
21712 { # default
21713 return $Dir."/src_compat_report.$ReportFormat";
21714 }
21715 }
21716 else
21717 {
21718 if($OutputReportPath)
21719 { # --report-path
21720 return $OutputReportPath;
21721 }
21722 else
21723 { # default
21724 return $Dir."/compat_report.$ReportFormat";
21725 }
21726 }
21727}
21728
21729sub printStatMsg($)
21730{
21731 my $Level = $_[0];
21732 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21733}
21734
21735sub listAffected($)
21736{
21737 my $Level = $_[0];
21738 my $List = "";
21739 foreach (keys(%{$TotalAffected{$Level}}))
21740 {
21741 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21742 { # skip "Low"-severity problems
21743 next;
21744 }
21745 $List .= "$_\n";
21746 }
21747 my $Dir = get_dirname(getReportPath($Level));
21748 if($Level eq "Binary") {
21749 writeFile($Dir."/abi_affected.txt", $List);
21750 }
21751 elsif($Level eq "Source") {
21752 writeFile($Dir."/src_affected.txt", $List);
21753 }
21754}
21755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021756sub printReport()
21757{
21758 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021759 createReport();
21760 if($JoinReport or $DoubleReport)
21761 {
21762 if($RESULT{"Binary"}{"Problems"}
21763 or $RESULT{"Source"}{"Problems"}) {
21764 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021766 else {
21767 printMsg("INFO", "result: COMPATIBLE");
21768 }
21769 printStatMsg("Binary");
21770 printStatMsg("Source");
21771 if($ListAffected)
21772 { # --list-affected
21773 listAffected("Binary");
21774 listAffected("Source");
21775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021776 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021777 elsif($BinaryOnly)
21778 {
21779 if($RESULT{"Binary"}{"Problems"}) {
21780 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21781 }
21782 else {
21783 printMsg("INFO", "result: COMPATIBLE");
21784 }
21785 printStatMsg("Binary");
21786 if($ListAffected)
21787 { # --list-affected
21788 listAffected("Binary");
21789 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021791 elsif($SourceOnly)
21792 {
21793 if($RESULT{"Source"}{"Problems"}) {
21794 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21795 }
21796 else {
21797 printMsg("INFO", "result: COMPATIBLE");
21798 }
21799 printStatMsg("Source");
21800 if($ListAffected)
21801 { # --list-affected
21802 listAffected("Source");
21803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021805 if($StdOut)
21806 {
21807 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021808 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021809 printMsg("INFO", "compatibility report has been generated to stdout");
21810 }
21811 else
21812 { # default
21813 printMsg("INFO", "compatibility reports have been generated to stdout");
21814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021815 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021816 else
21817 {
21818 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021819 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021820 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21821 }
21822 elsif($DoubleReport)
21823 { # default
21824 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21825 }
21826 elsif($BinaryOnly)
21827 { # --binary
21828 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21829 }
21830 elsif($SourceOnly)
21831 { # --source
21832 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021834 }
21835}
21836
21837sub check_win32_env()
21838{
21839 if(not $ENV{"DevEnvDir"}
21840 or not $ENV{"LIB"}) {
21841 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21842 }
21843}
21844
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021845sub diffSets($$)
21846{
21847 my ($S1, $S2) = @_;
21848 my @SK1 = keys(%{$S1});
21849 my @SK2 = keys(%{$S2});
21850 if($#SK1!=$#SK2) {
21851 return 1;
21852 }
21853 foreach my $K1 (@SK1)
21854 {
21855 if(not defined $S2->{$K1}) {
21856 return 1;
21857 }
21858 }
21859 return 0;
21860}
21861
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021862sub defaultDumpPath($$)
21863{
21864 my ($N, $V) = @_;
21865 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21866}
21867
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021868sub create_ABI_Dump()
21869{
21870 if(not -e $DumpAPI) {
21871 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21872 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021873
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021874 if(isDump($DumpAPI)) {
21875 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021876 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021877 else {
21878 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021879 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021880
21881 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021882 { # set to default: N
21883 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021884 }
21885
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021886 initLogging(1);
21887 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021888
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021889 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021890 if($OutputDumpPath)
21891 { # user defined path
21892 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021893 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021894 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21895
21896 if(not $Archive and not $StdOut)
21897 { # check archive utilities
21898 if($OSgroup eq "windows")
21899 { # using zip
21900 my $ZipCmd = get_CmdPath("zip");
21901 if(not $ZipCmd) {
21902 exitStatus("Not_Found", "can't find \"zip\"");
21903 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021904 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021905 else
21906 { # using tar and gzip
21907 my $TarCmd = get_CmdPath("tar");
21908 if(not $TarCmd) {
21909 exitStatus("Not_Found", "can't find \"tar\"");
21910 }
21911 my $GzipCmd = get_CmdPath("gzip");
21912 if(not $GzipCmd) {
21913 exitStatus("Not_Found", "can't find \"gzip\"");
21914 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021915 }
21916 }
21917
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021918 if(not $Descriptor{1}{"Dump"})
21919 {
21920 if(not $CheckHeadersOnly) {
21921 readLibs(1);
21922 }
21923 if($CheckHeadersOnly) {
21924 setLanguage(1, "C++");
21925 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021926 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021927 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021928 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021929 if(not $Descriptor{1}{"Dump"})
21930 {
21931 if($Descriptor{1}{"Headers"}) {
21932 readHeaders(1);
21933 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021934 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021935 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021936 if(not keys(%{$SymbolInfo{1}}))
21937 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021938 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021939 {
21940 if($CheckHeadersOnly) {
21941 exitStatus("Empty_Set", "the set of public symbols is empty");
21942 }
21943 else {
21944 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21945 }
21946 }
21947 }
21948 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021949 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021950 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21951 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021952 if($ExtraDump)
21953 { # add unmangled names to the ABI dump
21954 my @Names = ();
21955 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21956 {
21957 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21958 push(@Names, $MnglName);
21959 }
21960 }
21961 translateSymbols(@Names, 1);
21962 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21963 {
21964 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21965 {
21966 if(my $Unmangled = $tr_name{$MnglName})
21967 {
21968 if($MnglName ne $Unmangled) {
21969 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21970 }
21971 }
21972 }
21973 }
21974 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021975
21976 my %GccConstants = (); # built-in GCC constants
21977 foreach my $Name (keys(%{$Constants{1}}))
21978 {
21979 if(not defined $Constants{1}{$Name}{"Header"})
21980 {
21981 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21982 delete($Constants{1}{$Name});
21983 }
21984 }
21985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021986 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021987 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021988 "TypeInfo" => $TypeInfo{1},
21989 "SymbolInfo" => $SymbolInfo{1},
21990 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021991 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 "SymbolVersion" => $SymVer{1},
21993 "LibraryVersion" => $Descriptor{1}{"Version"},
21994 "LibraryName" => $TargetLibraryName,
21995 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021996 "SkipTypes" => $SkipTypes{1},
21997 "SkipSymbols" => $SkipSymbols{1},
21998 "SkipNameSpaces" => $SkipNameSpaces{1},
21999 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022000 "Headers" => \%HeadersInfo,
22001 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022002 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022003 "NameSpaces" => $NestedNameSpaces{1},
22004 "Target" => $OStarget,
22005 "Arch" => getArch(1),
22006 "WordSize" => $WORD_SIZE{1},
22007 "GccVersion" => get_dumpversion($GCC_PATH),
22008 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
22009 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
22010 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022011 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022012 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022013 }
22014 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022015 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022017 if($ExtendedCheck)
22018 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022019 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022020 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022021 if($BinaryOnly)
22022 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022023 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022024 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022025 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022026 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022027 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022028 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
22029 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022030 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022031
22032 my $ABI_DUMP = "";
22033 if($UseXML)
22034 {
22035 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022036 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022037 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022038 else
22039 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022040 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022042 if($StdOut)
22043 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022044 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022045 printMsg("INFO", "ABI dump has been generated to stdout");
22046 return;
22047 }
22048 else
22049 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022050 my ($DDir, $DName) = separate_path($DumpPath);
22051 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022052 if(not $Archive) {
22053 $DPath = $DumpPath;
22054 }
22055
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022057
22058 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022059 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022060 close(DUMP);
22061
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022062 if(not -s $DPath) {
22063 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
22064 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022065 if($Archive) {
22066 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022067 }
22068
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022069 if($OutputDumpPath) {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022070 printMsg("INFO", "dump path: $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040022071 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022072 else {
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022073 printMsg("INFO", "dump path: $DumpPath");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040022074 }
Andrey Ponomarenko9e05bee2016-04-03 15:57:20 +030022075 # 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 +040022076 }
22077}
22078
22079sub quickEmptyReports()
22080{ # Quick "empty" reports
22081 # 4 times faster than merging equal dumps
22082 # NOTE: the dump contains the "LibraryVersion" attribute
22083 # if you change the version, then your dump will be different
22084 # OVERCOME: use -v1 and v2 options for comparing dumps
22085 # and don't change version in the XML descriptor (and dumps)
22086 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
22087 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
22088 {
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022089 my $FilePath1 = $Descriptor{1}{"Path"};
22090 my $FilePath2 = $Descriptor{2}{"Path"};
22091
22092 if(not isDump_U($FilePath1)) {
22093 $FilePath1 = unpackDump($FilePath1);
22094 }
22095
22096 if(not isDump_U($FilePath2)) {
22097 $FilePath2 = unpackDump($FilePath2);
22098 }
22099
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022100 if($FilePath1 and $FilePath2)
22101 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022102 my $Line = readLineNum($FilePath1, 0);
22103 if($Line=~/xml/)
22104 { # XML format
22105 # is not supported yet
22106 return;
22107 }
22108
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022109 local $/ = undef;
22110
22111 open(DUMP1, $FilePath1);
22112 my $Content1 = <DUMP1>;
22113 close(DUMP1);
22114
22115 open(DUMP2, $FilePath2);
22116 my $Content2 = <DUMP2>;
22117 close(DUMP2);
22118
22119 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022120 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022121 # clean memory
22122 undef $Content2;
22123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022124 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022125 my $ABIdump = eval($Content1);
22126
22127 # clean memory
22128 undef $Content1;
22129
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022130 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022131 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 +040022132 }
22133 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022134 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022135 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22136 }
22137 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022138 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022139 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22140 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022141 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022142 read_Libs_DumpInfo($ABIdump, 1);
22143 read_Machine_DumpInfo($ABIdump, 1);
22144 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022145
22146 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22147 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22148
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022149 foreach my $S (keys(%{$ABIdump->{"SymbolInfo"}}))
22150 {
22151 if(my $Class = $ABIdump->{"SymbolInfo"}{$S}{"Class"})
22152 {
22153 if(defined $ABIdump->{"TypeInfo"}{$Class}{"PrivateABI"}) {
22154 next;
22155 }
22156 }
22157
22158 my $Access = $ABIdump->{"SymbolInfo"}{$S}{"Access"};
22159 if($Access ne "private")
22160 {
22161 $CheckedSymbols{"Binary"}{$S} = 1;
22162 $CheckedSymbols{"Source"}{$S} = 1;
22163 }
22164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022166 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22167 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22168 exitReport();
22169 }
22170 }
22171 }
22172}
22173
22174sub initLogging($)
22175{
22176 my $LibVersion = $_[0];
22177 # create log directory
22178 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22179 if($OutputLogPath{$LibVersion})
22180 { # user-defined by -log-path option
22181 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22182 }
22183 if($LogMode ne "n") {
22184 mkpath($LOG_DIR);
22185 }
22186 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022187 if($Debug)
22188 { # debug directory
22189 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022190
22191 if(not $ExtraInfo)
22192 { # enable --extra-info
22193 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22194 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022196 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022197}
22198
22199sub writeLog($$)
22200{
22201 my ($LibVersion, $Msg) = @_;
22202 if($LogMode ne "n") {
22203 appendFile($LOG_PATH{$LibVersion}, $Msg);
22204 }
22205}
22206
22207sub resetLogging($)
22208{
22209 my $LibVersion = $_[0];
22210 if($LogMode!~/a|n/)
22211 { # remove old log
22212 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022213 if($Debug) {
22214 rmtree($DEBUG_PATH{$LibVersion});
22215 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022216 }
22217}
22218
22219sub printErrorLog($)
22220{
22221 my $LibVersion = $_[0];
22222 if($LogMode ne "n") {
22223 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22224 }
22225}
22226
22227sub isDump($)
22228{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022229 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
22230 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022231 return $1;
22232 }
22233 return 0;
22234}
22235
22236sub isDump_U($)
22237{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040022238 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022239 return $1;
22240 }
22241 return 0;
22242}
22243
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022244sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022245{
22246 # read input XML descriptors or ABI dumps
22247 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022248 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022249 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022250 if(not -e $Descriptor{1}{"Path"}) {
22251 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022252 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022253
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022254 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022255 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022256 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022257 if(not -e $Descriptor{2}{"Path"}) {
22258 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022259 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022260
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022261 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022262 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 and isDump($Descriptor{2}{"Path"}))
22264 { # optimization: equal ABI dumps
22265 quickEmptyReports();
22266 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022267
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022268 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022269
22270 if(isDump($Descriptor{1}{"Path"})) {
22271 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022272 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022273 else {
22274 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
22275 }
22276
22277 if(isDump($Descriptor{2}{"Path"})) {
22278 read_ABI_Dump(2, $Descriptor{2}{"Path"});
22279 }
22280 else {
22281 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022282 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022283
22284 if(not $Descriptor{1}{"Version"})
22285 { # set to default: X
22286 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022287 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022288 }
22289
22290 if(not $Descriptor{2}{"Version"})
22291 { # set to default: Y
22292 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022293 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022294 }
22295
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022296 if(not $UsedDump{1}{"V"}) {
22297 initLogging(1);
22298 }
22299
22300 if(not $UsedDump{2}{"V"}) {
22301 initLogging(2);
22302 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022303
22304 # check input data
22305 if(not $Descriptor{1}{"Headers"}) {
22306 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022307 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022308 if(not $Descriptor{2}{"Headers"}) {
22309 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022310 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022311
22312 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022313 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022314 if(not $Descriptor{1}{"Libs"}) {
22315 exitStatus("Error", "can't find libraries info in descriptor d1");
22316 }
22317 if(not $Descriptor{2}{"Libs"}) {
22318 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 }
22320 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022321
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022322 if($UseDumps)
22323 { # --use-dumps
22324 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022325 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22326 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022327
22328 unlink($DumpPath1);
22329 unlink($DumpPath2);
22330
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022331 my $pid = fork();
22332 if($pid)
22333 { # dump on two CPU cores
22334 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22335 if($RelativeDirectory{1}) {
22336 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22337 }
22338 if($OutputLogPath{1}) {
22339 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22340 }
22341 if($CrossGcc) {
22342 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22343 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022344 if($Quiet)
22345 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022346 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022347 @PARAMS = (@PARAMS, "-logging-mode", "a");
22348 }
22349 elsif($LogMode and $LogMode ne "w")
22350 { # "w" is default
22351 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022352 }
22353 if($ExtendedCheck) {
22354 @PARAMS = (@PARAMS, "-extended");
22355 }
22356 if($UserLang) {
22357 @PARAMS = (@PARAMS, "-lang", $UserLang);
22358 }
22359 if($TargetVersion{1}) {
22360 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022362 if($BinaryOnly) {
22363 @PARAMS = (@PARAMS, "-binary");
22364 }
22365 if($SourceOnly) {
22366 @PARAMS = (@PARAMS, "-source");
22367 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022368 if($SortDump) {
22369 @PARAMS = (@PARAMS, "-sort");
22370 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022371 if($DumpFormat and $DumpFormat ne "perl") {
22372 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22373 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022374 if($CheckHeadersOnly) {
22375 @PARAMS = (@PARAMS, "-headers-only");
22376 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022377 if($Debug)
22378 {
22379 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022380 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022382 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022383 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022384 exit(1);
22385 }
22386 }
22387 else
22388 { # child
22389 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22390 if($RelativeDirectory{2}) {
22391 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22392 }
22393 if($OutputLogPath{2}) {
22394 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22395 }
22396 if($CrossGcc) {
22397 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22398 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022399 if($Quiet)
22400 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022401 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022402 @PARAMS = (@PARAMS, "-logging-mode", "a");
22403 }
22404 elsif($LogMode and $LogMode ne "w")
22405 { # "w" is default
22406 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022407 }
22408 if($ExtendedCheck) {
22409 @PARAMS = (@PARAMS, "-extended");
22410 }
22411 if($UserLang) {
22412 @PARAMS = (@PARAMS, "-lang", $UserLang);
22413 }
22414 if($TargetVersion{2}) {
22415 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22416 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022417 if($BinaryOnly) {
22418 @PARAMS = (@PARAMS, "-binary");
22419 }
22420 if($SourceOnly) {
22421 @PARAMS = (@PARAMS, "-source");
22422 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022423 if($SortDump) {
22424 @PARAMS = (@PARAMS, "-sort");
22425 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022426 if($DumpFormat and $DumpFormat ne "perl") {
22427 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22428 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022429 if($CheckHeadersOnly) {
22430 @PARAMS = (@PARAMS, "-headers-only");
22431 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022432 if($Debug)
22433 {
22434 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022435 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022436 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022437 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022438 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022439 exit(1);
22440 }
22441 else {
22442 exit(0);
22443 }
22444 }
22445 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022447 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022448 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22449 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022450 if($TargetTitle ne $TargetLibraryName) {
22451 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022452 }
22453 if($ShowRetVal) {
22454 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22455 }
22456 if($CrossGcc) {
22457 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22458 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022459 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22460 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022461 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022462 }
22463 if($ReportFormat and $ReportFormat ne "html")
22464 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022465 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022467 if($OutputReportPath) {
22468 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22469 }
22470 if($BinaryReportPath) {
22471 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22472 }
22473 if($SourceReportPath) {
22474 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22475 }
22476 if($LoggingPath) {
22477 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22478 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022479 if($CheckHeadersOnly) {
22480 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22481 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022482 if($BinaryOnly) {
22483 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22484 }
22485 if($SourceOnly) {
22486 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022488 if($Debug)
22489 {
22490 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22491 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022493 system("perl", $0, @CMP_PARAMS);
22494 exit($?>>8);
22495 }
22496 if(not $Descriptor{1}{"Dump"}
22497 or not $Descriptor{2}{"Dump"})
22498 { # need GCC toolchain to analyze
22499 # header files and libraries
22500 detect_default_paths("inc|lib|gcc");
22501 }
22502 if(not $Descriptor{1}{"Dump"})
22503 {
22504 if(not $CheckHeadersOnly) {
22505 readLibs(1);
22506 }
22507 if($CheckHeadersOnly) {
22508 setLanguage(1, "C++");
22509 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022510 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022511 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022512 }
22513 if(not $Descriptor{2}{"Dump"})
22514 {
22515 if(not $CheckHeadersOnly) {
22516 readLibs(2);
22517 }
22518 if($CheckHeadersOnly) {
22519 setLanguage(2, "C++");
22520 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022521 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022522 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022523 }
22524 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22525 { # support for old ABI dumps
22526 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022527 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022528 {
22529 $WORD_SIZE{1} = $WORD_SIZE{2};
22530 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22531 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022532 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022533 {
22534 $WORD_SIZE{2} = $WORD_SIZE{1};
22535 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22536 }
22537 }
22538 elsif(not $WORD_SIZE{1}
22539 and not $WORD_SIZE{2})
22540 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022541 $WORD_SIZE{1} = "4";
22542 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022543 }
22544 if($Descriptor{1}{"Dump"})
22545 { # support for old ABI dumps
22546 prepareTypes(1);
22547 }
22548 if($Descriptor{2}{"Dump"})
22549 { # support for old ABI dumps
22550 prepareTypes(2);
22551 }
22552 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22553 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22554 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022555 # process input data
22556 if($Descriptor{1}{"Headers"}
22557 and not $Descriptor{1}{"Dump"}) {
22558 readHeaders(1);
22559 }
22560 if($Descriptor{2}{"Headers"}
22561 and not $Descriptor{2}{"Dump"}) {
22562 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022564
22565 # clean memory
22566 %SystemHeaders = ();
22567 %mangled_name_gcc = ();
22568
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022569 prepareSymbols(1);
22570 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022571
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022572 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022573 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022574
22575 # Virtual Tables
22576 registerVTable(1);
22577 registerVTable(2);
22578
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022579 if(not checkDump(1, "1.22")
22580 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022581 { # support for old ABI dumps
22582 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22583 {
22584 if($ClassName=~/</)
22585 { # templates
22586 if(not defined $VirtualTable{1}{$ClassName})
22587 { # synchronize
22588 delete($VirtualTable{2}{$ClassName});
22589 }
22590 }
22591 }
22592 }
22593
22594 registerOverriding(1);
22595 registerOverriding(2);
22596
22597 setVirtFuncPositions(1);
22598 setVirtFuncPositions(2);
22599
22600 # Other
22601 addParamNames(1);
22602 addParamNames(2);
22603
22604 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022605}
22606
22607sub compareAPIs($)
22608{
22609 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022610
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022611 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022612 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022613
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022614 if($Level eq "Binary") {
22615 printMsg("INFO", "comparing ABIs ...");
22616 }
22617 else {
22618 printMsg("INFO", "comparing APIs ...");
22619 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022620
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022621 if($CheckHeadersOnly
22622 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022623 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022624 detectAdded_H($Level);
22625 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022626 }
22627 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022628 { # added/removed in libs
22629 detectAdded($Level);
22630 detectRemoved($Level);
22631 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022632
22633 mergeSymbols($Level);
22634 if(keys(%{$CheckedSymbols{$Level}})) {
22635 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022636 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022637
22638 $Cache{"mergeTypes"} = (); # free memory
22639
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022640 if($CheckHeadersOnly
22641 or $Level eq "Source")
22642 { # added/removed in headers
22643 mergeHeaders($Level);
22644 }
22645 else
22646 { # added/removed in libs
22647 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022648 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022649
22650 foreach my $S (keys(%{$CompatProblems{$Level}}))
22651 {
22652 foreach my $K (keys(%{$CompatProblems{$Level}{$S}}))
22653 {
22654 foreach my $L (keys(%{$CompatProblems{$Level}{$S}{$K}}))
22655 {
22656 if(my $T = $CompatProblems{$Level}{$S}{$K}{$L}{"Type_Name"}) {
22657 $TypeProblemsIndex{$Level}{$T}{$S} = 1;
22658 }
22659 }
22660 }
22661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022662}
22663
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022664sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022665{
22666 my %Opts = (
22667 "OStarget"=>$OStarget,
22668 "Debug"=>$Debug,
22669 "Quiet"=>$Quiet,
22670 "LogMode"=>$LogMode,
22671 "CheckHeadersOnly"=>$CheckHeadersOnly,
22672
22673 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022674 "GCC_PATH"=>$GCC_PATH,
22675 "TargetSysInfo"=>$TargetSysInfo,
22676 "CrossPrefix"=>$CrossPrefix,
22677 "TargetLibraryName"=>$TargetLibraryName,
22678 "CrossGcc"=>$CrossGcc,
22679 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022680 "NoStdInc"=>$NoStdInc,
22681
22682 "BinaryOnly" => $BinaryOnly,
22683 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022684 );
22685 return \%Opts;
22686}
22687
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022688sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022689{
22690 my %CODE_ERROR = reverse(%ERROR_CODE);
22691 return $CODE_ERROR{$_[0]};
22692}
22693
22694sub scenario()
22695{
22696 if($StdOut)
22697 { # enable quiet mode
22698 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022699 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022700 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022701 if(not $LogMode)
22702 { # default
22703 $LogMode = "w";
22704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022705 if($UserLang)
22706 { # --lang=C++
22707 $UserLang = uc($UserLang);
22708 $COMMON_LANGUAGE{1}=$UserLang;
22709 $COMMON_LANGUAGE{2}=$UserLang;
22710 }
22711 if($LoggingPath)
22712 {
22713 $OutputLogPath{1} = $LoggingPath;
22714 $OutputLogPath{2} = $LoggingPath;
22715 if($Quiet) {
22716 $COMMON_LOG_PATH = $LoggingPath;
22717 }
22718 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022719
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022720 if($Quick) {
22721 $ADD_TMPL_INSTANCES = 0;
22722 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022723 if($OutputDumpPath)
22724 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022725 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022726 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22727 }
22728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022729 if($BinaryOnly and $SourceOnly)
22730 { # both --binary and --source
22731 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022732 if(not $CmpSystems)
22733 {
22734 $BinaryOnly = 0;
22735 $SourceOnly = 0;
22736 }
22737
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022738 $DoubleReport = 1;
22739 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022740
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022741 if($OutputReportPath)
22742 { # --report-path
22743 $DoubleReport = 0;
22744 $JoinReport = 1;
22745 }
22746 }
22747 elsif($BinaryOnly or $SourceOnly)
22748 { # --binary or --source
22749 $DoubleReport = 0;
22750 $JoinReport = 0;
22751 }
22752 if($UseXML)
22753 { # --xml option
22754 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022755 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022757 if($ReportFormat)
22758 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022759 $ReportFormat = lc($ReportFormat);
22760 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022761 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022762 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022763 if($ReportFormat eq "htm")
22764 { # HTM == HTML
22765 $ReportFormat = "html";
22766 }
22767 elsif($ReportFormat eq "xml")
22768 { # --report-format=XML equal to --xml
22769 $UseXML = 1;
22770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022771 }
22772 else
22773 { # default: HTML
22774 $ReportFormat = "html";
22775 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022776 if($DumpFormat)
22777 { # validate
22778 $DumpFormat = lc($DumpFormat);
22779 if($DumpFormat!~/\A(xml|perl)\Z/) {
22780 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22781 }
22782 if($DumpFormat eq "xml")
22783 { # --dump-format=XML equal to --xml
22784 $UseXML = 1;
22785 }
22786 }
22787 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022788 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022789 $DumpFormat = "perl";
22790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022791 if($Quiet and $LogMode!~/a|n/)
22792 { # --quiet log
22793 if(-f $COMMON_LOG_PATH) {
22794 unlink($COMMON_LOG_PATH);
22795 }
22796 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022797 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022798 $CheckUndefined = 1;
22799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022800 if($TestTool and $UseDumps)
22801 { # --test && --use-dumps == --test-dump
22802 $TestDump = 1;
22803 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022804 if($Tolerant)
22805 { # enable all
22806 $Tolerance = 1234;
22807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022808 if($Help)
22809 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022810 HELP_MESSAGE();
22811 exit(0);
22812 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022813 if($InfoMsg)
22814 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022815 INFO_MESSAGE();
22816 exit(0);
22817 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022818 if($ShowVersion)
22819 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022820 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 +040022821 exit(0);
22822 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022823 if($DumpVersion)
22824 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022825 printMsg("INFO", $TOOL_VERSION);
22826 exit(0);
22827 }
22828 if($ExtendedCheck) {
22829 $CheckHeadersOnly = 1;
22830 }
22831 if($SystemRoot_Opt)
22832 { # user defined root
22833 if(not -e $SystemRoot_Opt) {
22834 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22835 }
22836 $SystemRoot = $SystemRoot_Opt;
22837 $SystemRoot=~s/[\/]+\Z//g;
22838 if($SystemRoot) {
22839 $SystemRoot = get_abs_path($SystemRoot);
22840 }
22841 }
22842 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022843
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022844 if($SortDump)
22845 {
22846 $Data::Dumper::Useperl = 1;
22847 $Data::Dumper::Sortkeys = \&dump_sorting;
22848 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022849
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022850 if($TargetLibsPath)
22851 {
22852 if(not -f $TargetLibsPath) {
22853 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22854 }
22855 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22856 $TargetLibs{$Lib} = 1;
22857 }
22858 }
22859 if($TargetHeadersPath)
22860 { # --headers-list
22861 if(not -f $TargetHeadersPath) {
22862 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22863 }
22864 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22865 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022866 $TargetHeaders{1}{get_filename($Header)} = 1;
22867 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022868 }
22869 }
22870 if($TargetHeader)
22871 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022872 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22873 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022874 }
22875 if($TestTool
22876 or $TestDump)
22877 { # --test, --test-dump
22878 detect_default_paths("bin|gcc"); # to compile libs
22879 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022880 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenko0f946a42016-07-02 19:10:59 +030022881 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly, $OldStyle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022882 exit(0);
22883 }
22884 if($DumpSystem)
22885 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022886
22887 if(not $TargetSysInfo) {
22888 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22889 }
22890
22891 if(not -d $TargetSysInfo) {
22892 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22893 }
22894
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022895 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022896 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022897 { # system XML descriptor
22898 if(not -f $DumpSystem) {
22899 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22900 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022901
22902 my $SDesc = readFile($DumpSystem);
22903 if(my $RelDir = $RelativeDirectory{1}) {
22904 $SDesc =~ s/{RELPATH}/$RelDir/g;
22905 }
22906
22907 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022908 foreach (@{$Ret->{"Tools"}})
22909 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022910 push_U($SystemPaths{"bin"}, $_);
22911 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022912 }
22913 if($Ret->{"CrossPrefix"}) {
22914 $CrossPrefix = $Ret->{"CrossPrefix"};
22915 }
22916 }
22917 elsif($SystemRoot_Opt)
22918 { # -sysroot "/" option
22919 # default target: /usr/lib, /usr/include
22920 # search libs: /usr/lib and /lib
22921 if(not -e $SystemRoot."/usr/lib") {
22922 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22923 }
22924 if(not -e $SystemRoot."/lib") {
22925 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22926 }
22927 if(not -e $SystemRoot."/usr/include") {
22928 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22929 }
22930 readSystemDescriptor("
22931 <name>
22932 $DumpSystem
22933 </name>
22934 <headers>
22935 $SystemRoot/usr/include
22936 </headers>
22937 <libs>
22938 $SystemRoot/usr/lib
22939 </libs>
22940 <search_libs>
22941 $SystemRoot/lib
22942 </search_libs>");
22943 }
22944 else {
22945 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22946 }
22947 detect_default_paths("bin|gcc"); # to check symbols
22948 if($OStarget eq "windows")
22949 { # to run dumpbin.exe
22950 # and undname.exe
22951 check_win32_env();
22952 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022953 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022954 exit(0);
22955 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022957 if($CmpSystems)
22958 { # --cmp-systems
22959 detect_default_paths("bin"); # to extract dumps
22960 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022961 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022962 exit(0);
22963 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022964
22965 if(not $CountSymbols)
22966 {
22967 if(not $TargetLibraryName) {
22968 exitStatus("Error", "library name is not selected (-l option)");
22969 }
22970 else
22971 { # validate library name
22972 if($TargetLibraryName=~/[\*\/\\]/) {
22973 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022975 }
22976 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030022977
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022978 if(not $TargetTitle) {
22979 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022980 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022981
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022982 if($SymbolsListPath)
22983 {
22984 if(not -f $SymbolsListPath) {
22985 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22986 }
22987 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22988 $SymbolsList{$Interface} = 1;
22989 }
22990 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022991 if($TypesListPath)
22992 {
22993 if(not -f $TypesListPath) {
22994 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22995 }
22996 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22997 $TypesList{$Type} = 1;
22998 }
22999 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023000 if($SkipSymbolsListPath)
23001 {
23002 if(not -f $SkipSymbolsListPath) {
23003 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
23004 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030023005 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
23006 {
23007 $SkipSymbols{1}{$Interface} = 1;
23008 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040023009 }
23010 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030023011 if($SkipTypesListPath)
23012 {
23013 if(not -f $SkipTypesListPath) {
23014 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
23015 }
23016 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
23017 {
23018 $SkipTypes{1}{$Type} = 1;
23019 $SkipTypes{2}{$Type} = 1;
23020 }
23021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023022 if($SkipHeadersPath)
23023 {
23024 if(not -f $SkipHeadersPath) {
23025 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
23026 }
23027 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023028 { # register for both versions
23029 $SkipHeadersList{1}{$Path} = 1;
23030 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkob3118d92016-05-14 17:55:06 +030023031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023032 my ($CPath, $Type) = classifyPath($Path);
23033 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023034 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023035 }
23036 }
23037 if($ParamNamesPath)
23038 {
23039 if(not -f $ParamNamesPath) {
23040 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
23041 }
23042 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
23043 {
23044 if($Line=~s/\A(\w+)\;//)
23045 {
23046 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023047 if($Line=~/;(\d+);/)
23048 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023049 while($Line=~s/(\d+);(\w+)//) {
23050 $AddIntParams{$Interface}{$1}=$2;
23051 }
23052 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040023053 else
23054 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023055 my $Num = 0;
23056 foreach my $Name (split(/;/, $Line)) {
23057 $AddIntParams{$Interface}{$Num++}=$Name;
23058 }
23059 }
23060 }
23061 }
23062 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023063
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023064 if($AppPath)
23065 {
23066 if(not -f $AppPath) {
23067 exitStatus("Access_Error", "can't access file \'$AppPath\'");
23068 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030023069
23070 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040023071 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023072 $SymbolsList_App{$Interface} = 1;
23073 }
23074 }
Andrey Ponomarenko447e7d52016-05-20 19:12:20 +030023075
23076 if($CountSymbols)
23077 {
23078 if(not -e $CountSymbols) {
23079 exitStatus("Access_Error", "can't access \'$CountSymbols\'");
23080 }
23081
23082 read_ABI_Dump(1, $CountSymbols);
23083
23084 foreach my $Id (keys(%{$SymbolInfo{1}}))
23085 {
23086 my $MnglName = $SymbolInfo{1}{$Id}{"MnglName"};
23087 if(not $MnglName) {
23088 $MnglName = $SymbolInfo{1}{$Id}{"ShortName"}
23089 }
23090
23091 if(my $SV = $SymVer{1}{$MnglName}) {
23092 $CompleteSignature{1}{$SV} = $SymbolInfo{1}{$Id};
23093 }
23094 else {
23095 $CompleteSignature{1}{$MnglName} = $SymbolInfo{1}{$Id};
23096 }
23097
23098 if(my $Alias = $CompleteSignature{1}{$MnglName}{"Alias"}) {
23099 $CompleteSignature{1}{$Alias} = $SymbolInfo{1}{$Id};
23100 }
23101 }
23102
23103 my $Count = 0;
23104 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
23105 {
23106 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
23107 next;
23108 }
23109 if($CompleteSignature{1}{$Symbol}{"Private"}) {
23110 next;
23111 }
23112 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
23113 next;
23114 }
23115
23116 $Count += symbolFilter($Symbol, 1, "Affected + InlineVirt", "Binary");
23117 }
23118
23119 printMsg("INFO", $Count);
23120 exit(0);
23121 }
23122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023123 if($DumpAPI)
23124 { # --dump-abi
23125 # make an API dump
23126 create_ABI_Dump();
23127 exit($COMPILE_ERRORS);
23128 }
23129 # default: compare APIs
23130 # -d1 <path>
23131 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040023132 compareInit();
23133 if($JoinReport or $DoubleReport)
23134 {
23135 compareAPIs("Binary");
23136 compareAPIs("Source");
23137 }
23138 elsif($BinaryOnly) {
23139 compareAPIs("Binary");
23140 }
23141 elsif($SourceOnly) {
23142 compareAPIs("Source");
23143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040023144 exitReport();
23145}
23146
23147scenario();